diff --git a/compiler/lib/src/main/scala/analysis/Analysis.scala b/compiler/lib/src/main/scala/analysis/Analysis.scala index 168f3014c..ddbf74d17 100644 --- a/compiler/lib/src/main/scala/analysis/Analysis.scala +++ b/compiler/lib/src/main/scala/analysis/Analysis.scala @@ -469,6 +469,9 @@ case class Analysis( case a: Type.Array => val id = a.node._2.data.eltType.id getElementReason(id) + case v: Type.Vector => + val id = v.node._2.data.eltType.id + getElementReason(id) case s: Type.Struct => val idOpt = s.node._2.data.members.map(_._2.data.typeName.id).find( id => !this.typeMap(id).isDisplayable diff --git a/compiler/lib/src/main/scala/analysis/Analyzers/BasicUseAnalyzer.scala b/compiler/lib/src/main/scala/analysis/Analyzers/BasicUseAnalyzer.scala index 52ddae861..04d9d9a8e 100644 --- a/compiler/lib/src/main/scala/analysis/Analyzers/BasicUseAnalyzer.scala +++ b/compiler/lib/src/main/scala/analysis/Analyzers/BasicUseAnalyzer.scala @@ -81,6 +81,16 @@ trait BasicUseAnalyzer extends TypeExpressionAnalyzer { } yield a } + override def defVectorAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefVector]]) = { + // A vector whose size specifier omits a size-prefix type has an implied + // use of the framework type FwSizeStoreType (see ConstructImpliedUseMap). + val id = node._2.id + for { + a <- visitImpliedUses(a, id) + a <- super.defVectorAnnotatedNode(a, node) + } yield a + } + override def defTopologyAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefTopology]]) = { val id = node._2.id for { diff --git a/compiler/lib/src/main/scala/analysis/Analyzers/TypeExpressionAnalyzer.scala b/compiler/lib/src/main/scala/analysis/Analyzers/TypeExpressionAnalyzer.scala index 49453d8d0..2ba1b8c7a 100644 --- a/compiler/lib/src/main/scala/analysis/Analyzers/TypeExpressionAnalyzer.scala +++ b/compiler/lib/src/main/scala/analysis/Analyzers/TypeExpressionAnalyzer.scala @@ -70,6 +70,17 @@ trait TypeExpressionAnalyzer } yield a } + override def defVectorAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefVector]]) = { + val (_, node1, _) = node + val data = node1.data + for { + a <- exprNode(a, data.size) + a <- opt(typeNameNode)(a, data.sizePrefixType) + a <- typeNameNode(a, data.eltType) + a <- opt(exprNode)(a, data.default) + } yield a + } + override def defComponentInstanceAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefComponentInstance]]) = { val (_, node1, _) = node val data = node1.data diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckDictionaryDefs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckDictionaryDefs.scala index fd3f826b9..fdba781ef 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckDictionaryDefs.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckDictionaryDefs.scala @@ -50,6 +50,9 @@ object CheckDictionaryDefs override def defStructAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefStruct]]) = checkTypeDef(a, Symbol.Struct(aNode)) + override def defVectorAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefVector]]) = + checkTypeDef(a, Symbol.Vector(aNode)) + override def defConstantAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefConstant]]) = checkConstantDef(a, Symbol.Constant(aNode)) diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckExprTypes.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckExprTypes.scala index 5c1dba4f1..cc67cf7a8 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckExprTypes.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckExprTypes.scala @@ -51,6 +51,25 @@ object CheckExprTypes extends UseAnalyzer { } yield a } + override def defVectorAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefVector]]) = { + val (_, node, _) = aNode + val data = node.data + for { + a <- super.defVectorAnnotatedNode(a, aNode) + _ <- convertNodeToNumeric(a, data.size) + _ <- data.default match { + case Some(defaultNode) => + val vectorId = node.id + val vectorType = a.typeMap(vectorId) + val defaultId = defaultNode.id + val defaultType = a.typeMap(defaultId) + val loc = Locations.get(defaultId) + Analysis.convertTypes(loc, defaultType -> vectorType) + case None => Right(a) + } + } yield a + } + override def defConstantAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefConstant]]) = { val (_, node,_) = aNode if (!a.typeMap.contains(node.id)) { diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckFrameworkDefs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckFrameworkDefs.scala index 34676737a..3e35d271c 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckFrameworkDefs.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckFrameworkDefs.scala @@ -40,6 +40,9 @@ object CheckFrameworkDefs override def defStructAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefStruct]]) = analyzeType(a, Symbol.Struct(aNode)) + override def defVectorAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefVector]]) = + analyzeType(a, Symbol.Vector(aNode)) + private val constants = Map( "FW_ASSERT_COUNT_MAX" -> requireIntegerConstant, "FW_CMD_ARG_BUFFER_MAX_SIZE" -> requireIntegerConstant, diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckSpecLocs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckSpecLocs.scala index 6c36a0e3e..e44357051 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckSpecLocs.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckSpecLocs.scala @@ -64,6 +64,11 @@ object CheckSpecLocs aNode: Ast.Annotated[AstNode[Ast.DefStruct]] ) = checkSpecLoc(a, Ast.SpecLoc.Type, Symbol.Struct(aNode)) + override def defVectorAnnotatedNode( + a: Analysis, + aNode: Ast.Annotated[AstNode[Ast.DefVector]] + ) = checkSpecLoc(a, Ast.SpecLoc.Type, Symbol.Vector(aNode)) + override def defSystemAnnotatedNode( a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefSystem]] diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTypeUses.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTypeUses.scala index 28dd5ce11..8a3dfa28a 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTypeUses.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTypeUses.scala @@ -111,6 +111,41 @@ object CheckTypeUses extends UseAnalyzer { visitIfNeeded(visitor)(a, aNode) } + override def defVectorAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefVector]]) = { + def visitor(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefVector]]) = + for { + a <- super.defVectorAnnotatedNode(a, aNode) + // Resolve and check the size-prefix type, if present. + // Its underlying type must be an unsigned primitive integer type. + sizePrefixType <- { + val data = aNode._2.data + data.sizePrefixType match { + case Some(typeName) => + val t = a.typeMap(typeName.id) + val loc = Locations.get(typeName.id) + t.getUnderlyingType match { + case pi : Type.PrimitiveInt + if pi.signedness == Type.PrimitiveInt.Unsigned => Right(Some(t)) + case _ => Left(SemanticError.InvalidType( + loc, + "vector size-prefix type must be an unsigned primitive integer type" + )) + } + case None => Right(None) + } + } + } + yield { + val (_, node, _) = aNode + val data = node.data + val eltType = a.typeMap(data.eltType.id) + val anonVector = Type.AnonVector(None, eltType) + val t = Type.Vector(aNode, anonVector, sizePrefixType) + a.assignType(node -> t) + } + visitIfNeeded(visitor)(a, aNode) + } + override def exprNode(a: Analysis, node: AstNode[Ast.Expr]) = matchExprNode(a, node) override def typeNameBoolNode(a: Analysis, node: AstNode[Ast.TypeName]) = @@ -154,6 +189,7 @@ object CheckTypeUses extends UseAnalyzer { case Symbol.Array(node) => defArrayAnnotatedNode(a, node) case Symbol.Enum(node) => defEnumAnnotatedNode(a, node) case Symbol.Struct(node) => defStructAnnotatedNode(a, node) + case Symbol.Vector(node) => defVectorAnnotatedNode(a, node) case _ => Right(a) } t <- a.typeMap.get(symbol.getNodeId) match { diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckUseDefCycles.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckUseDefCycles.scala index 9e0c2fc7d..51972a098 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckUseDefCycles.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckUseDefCycles.scala @@ -39,6 +39,11 @@ object CheckUseDefCycles extends UseAnalyzer { visitDefPost(a, symbol, node, super.defStructAnnotatedNode) } + override def defVectorAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefVector]]) = { + val symbol = Symbol.Vector(node) + visitDefPost(a, symbol, node, super.defVectorAnnotatedNode) + } + override def defTopologyAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefTopology]]) = { val symbol = Symbol.Topology(node) visitDefPost(a, symbol, node, super.defTopologyAnnotatedNode) @@ -77,6 +82,7 @@ object CheckUseDefCycles extends UseAnalyzer { case Symbol.Interface(node) => defInterfaceAnnotatedNode(a, node) case Symbol.Struct(node) => defStructAnnotatedNode(a, node) case Symbol.Topology(node) => defTopologyAnnotatedNode(a, node) + case Symbol.Vector(node) => defVectorAnnotatedNode(a, node) case _ => Right(a) } } diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/ConstructImpliedUseMap.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/ConstructImpliedUseMap.scala index ab82f8e16..99e307404 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/ConstructImpliedUseMap.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/ConstructImpliedUseMap.scala @@ -84,8 +84,34 @@ object ConstructImpliedUseMap extends TypeExpressionAnalyzer { Right(a) } + override def defVectorAnnotatedNode( + a: Analysis, + aNode: Ast.Annotated[AstNode[Ast.DefVector]] + ) = { + val node = aNode._2 + val id = node.id + val a1 = node.data.sizePrefixType match { + // An explicit size-prefix type is an ordinary type use, handled by the + // superclass recursion. No implied use. + case Some(_) => a + // When the size-prefix type is omitted, the size specifier represents an + // implied use of the framework type FwSizeStoreType. + case None => + val identList = List("FwSizeStoreType") + val id1 = ImpliedUse.replicateId(id) + val impliedUse = ImpliedUse.fromIdentListAndId( + identList, + id1, + List("use of a vector type without a size-prefix type requires this definition") + ) + val map = Map(ImpliedUse.Kind.Type -> Set(impliedUse)) + a.copy(impliedUseMap = a.impliedUseMap + (id -> map)) + } + super.defVectorAnnotatedNode(a1, aNode) + } + override def typeNameStringNode( - a: Analysis, + a: Analysis, node: AstNode[Ast.TypeName], tn: Ast.TypeNameString ) = { diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/EnterSymbols.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/EnterSymbols.scala index bceb96707..cff316980 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/EnterSymbols.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/EnterSymbols.scala @@ -317,6 +317,19 @@ object EnterSymbols yield updateMap(a, symbol).copy(nestedScope = nestedScope) } + override def defVectorAnnotatedNode( + a: Analysis, + aNode: Ast.Annotated[AstNode[Ast.DefVector]] + ) = { + val (_, node, _) = aNode + val data = node.data + val name = data.name + val symbol = Symbol.Vector(aNode) + val nestedScope = a.nestedScope + for (nestedScope <- nestedScope.put(NameGroup.Type)(name, symbol)) + yield updateMap(a, symbol).copy(nestedScope = nestedScope) + } + private def updateMap(a: Analysis, s: Symbol): Analysis = { val parentSymbolMap = a.parentSymbol.fold (a.parentSymbolMap) (ps => a.parentSymbolMap + (s -> ps) diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/EvalConstantExprs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/EvalConstantExprs.scala index b7ede9f10..fa9f2f453 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/EvalConstantExprs.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/EvalConstantExprs.scala @@ -298,6 +298,13 @@ object EvalConstantExprs extends UseAnalyzer { a <- FinalizeTypeDefs.defStructAnnotatedNode(a, t.node) } yield a + override def vector(a: Analysis, t: Type.Vector) = + for { + a <- defVectorAnnotatedNode(a, t.node) + a <- finalizeIfNeeded(a, t.anonVector.eltType) + a <- FinalizeTypeDefs.defVectorAnnotatedNode(a, t.node) + } yield a + // Query whether a type is finalized // A type is finalized if (1) it has a definition symbol S // and S is in the visited symbol set; or (2) diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/FinalizeTypeDefs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/FinalizeTypeDefs.scala index a72c33964..4a7d8ed05 100644 --- a/compiler/lib/src/main/scala/analysis/CheckSemantics/FinalizeTypeDefs.scala +++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/FinalizeTypeDefs.scala @@ -174,6 +174,60 @@ object FinalizeTypeDefs visitIfNeeded(symbol, visitor)(a, aNode) } + override def defVectorAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefVector]]) = { + val symbol = Symbol.Vector(aNode) + def visitor(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefVector]]) = { + val node = aNode._2 + val data = node.data + // Get the type of this node as a vector type V + val vectorType @ Type.Vector(_, _, _, _, _) = a.typeMap(node.id) + for { + // Visit the element type of V, to update its members + eltType <- TypeVisitor.ty(a, vectorType.anonVector.eltType) + // Visit the size-prefix type of V, if present, to resolve aliases + sizePrefixType <- vectorType.sizePrefixType match { + case Some(t) => for (t1 <- TypeVisitor.ty(a, t)) yield Some(t1) + case None => Right(None) + } + // Update the maximum size, element type, and size-prefix type in V + size <- a.getArraySize(data.size.id) + vectorType <- { + val anonVector = Type.AnonVector(Some(size.toInt), eltType) + Right(vectorType.copy(anonVector = anonVector, sizePrefixType = sizePrefixType)) + } + // Compute the default value + default <- data.default match { + case Some(defaultNode) => { + val id = defaultNode.id + val v = a.valueMap(id) + val loc = Locations.get(id) + for (_ <- Analysis.convertTypes(loc, v.getType -> vectorType)) + yield { + val vector @ Value.Vector(_, _) = Analysis.convertValueToType(v, vectorType) + vector + } + } + case None => { + // The default value is the empty vector, i.e., the value of length zero + Right(Value.Vector(Value.AnonArray(Nil), vectorType)) + } + } + // Compute the format + format <- Result.mapOpt( + data.format, + Analysis.computeFormat(_, List(eltType)) + ) + } + yield { + // Update the default value and format in V + val vectorType1 = vectorType.copy(default = Some(default), format = format) + // Update V in the type map + a.assignType(node -> vectorType1) + } + } + visitIfNeeded(symbol, visitor)(a, aNode) + } + override def transUnit(a: Analysis, tu: Ast.TransUnit) = super.transUnit(a.copy(visitedSymbolSet = Set()), tu) @@ -232,6 +286,14 @@ object FinalizeTypeDefs for (a <- defStructAnnotatedNode(a, t.node)) yield a.typeMap(t.node._2.id) + override def vector(a: Analysis, t: Type.Vector) = + for (a <- defVectorAnnotatedNode(a, t.node)) + yield a.typeMap(t.node._2.id) + + override def anonVector(a: Analysis, t: Type.AnonVector) = + for (eltType <- ty(a, t.eltType)) + yield Type.AnonVector(t.maxSize, eltType) + override def anonStruct(a: Analysis, t: Type.AnonStruct) = { def visitor(member: Type.Struct.Member): Result.Result[Type.Struct.Member] = for (memberType <- ty(a, member._2)) yield member._1 -> memberType diff --git a/compiler/lib/src/main/scala/analysis/Semantics/Symbol.scala b/compiler/lib/src/main/scala/analysis/Semantics/Symbol.scala index 91282441d..599ef3c59 100644 --- a/compiler/lib/src/main/scala/analysis/Semantics/Symbol.scala +++ b/compiler/lib/src/main/scala/analysis/Semantics/Symbol.scala @@ -77,6 +77,11 @@ object Symbol { override def getNodeId = node._2.id override def getUnqualifiedName = node._2.data.name } + final case class Vector(node: Ast.Annotated[AstNode[Ast.DefVector]]) extends TypeSymbol { + override def isDictionaryDef = node._2.data.isDictionaryDef + override def getNodeId = node._2.id + override def getUnqualifiedName = node._2.data.name + } final case class Topology(node: Ast.Annotated[AstNode[Ast.DefTopology]]) extends InterfaceInstanceSymbol { override def getNodeId = node._2.id override def getUnqualifiedName = node._2.data.name diff --git a/compiler/lib/src/main/scala/analysis/Semantics/Type.scala b/compiler/lib/src/main/scala/analysis/Semantics/Type.scala index 4e4b1ac98..8660f1e8b 100644 --- a/compiler/lib/src/main/scala/analysis/Semantics/Type.scala +++ b/compiler/lib/src/main/scala/analysis/Semantics/Type.scala @@ -260,6 +260,45 @@ object Type { } + /** A named vector type */ + case class Vector( + /** The AST node giving the definition */ + node: Ast.Annotated[AstNode[Ast.DefVector]], + /** The structurally equivalent anonymous vector */ + anonVector: AnonVector, + /** The resolved size-prefix type, if specified. + * If None, the size-prefix type is the framework type FwSizeStoreType. */ + sizePrefixType: Option[Type] = None, + /** The specified default value, if any */ + default: Option[Value.Vector] = None, + /** The specified format, if any */ + format: Option[Format] = None, + ) extends Type { + override def getDefaultValue: Option[Value.Vector] = default + /** Set the maximum size */ + def setMaxSize(size: Array.Size): Vector = + this.copy(anonVector = anonVector.setMaxSize(size)) + override def getDefSymbol = Some(Symbol.Vector(node)) + override def hasNumericMembers = anonVector.hasNumericMembers + override def isDisplayable = anonVector.eltType.isDisplayable + override def toString = "vector " ++ node._2.data.name + } + + object Vector { + + /** Check whether a length is allowed for a maximum size. + * Used when converting to a vector type. + * None on either side means "not yet known", which is permissive + * (the exact check is performed after finalizing type definitions). */ + def maxSizeAllows(length: Option[Array.Size], maxSize: Option[Array.Size]): Boolean = + (length, maxSize) match { + case (None, _) => true + case (_, None) => true + case (Some(k), Some(n)) => k <= n + } + + } + /** An enum type */ case class Enum( /** The AST node giving the definition */ @@ -350,6 +389,23 @@ object Type { } } + /** An anonymous vector type */ + case class AnonVector( + /** The maximum size */ + maxSize: Option[Array.Size], + /** The element type */ + eltType: Type + ) extends Type { + /** Set the maximum size */ + def setMaxSize(size: Array.Size): AnonVector = this.copy(maxSize = Some(size)) + override def getDefaultValue: Option[Value] = None + override def hasNumericMembers = eltType.hasNumericMembers + override def toString = maxSize match { + case Some(n) => "[size " ++ n.toString ++ "] " ++ eltType.toString + case None => "vector of " ++ eltType.toString + } + } + /** An anonymous struct type */ case class AnonStruct( /** The members */ @@ -428,6 +484,15 @@ object Type { t1.isPromotableToArray && t1.isConvertibleTo(eltType2) case _ => false } + def vector = pair match { + case Vector(_, anonVector1, _, _, _) -> _ => anonVector1.isConvertibleTo(t2) + case _ -> Vector(_, anonVector2, _, _, _) => t1.isConvertibleTo(anonVector2) + case AnonVector(size1, eltType1) -> AnonVector(size2, eltType2) => + Vector.maxSizeAllows(size1, size2) && eltType1.isConvertibleTo(eltType2) + case AnonArray(size1, eltType1) -> AnonVector(size2, eltType2) => + Vector.maxSizeAllows(size1, size2) && eltType1.isConvertibleTo(eltType2) + case _ => false + } def struct = { def memberExistsIn (members: Struct.Members) (member: Struct.Member): Boolean = members.get(member._1) match { @@ -451,6 +516,7 @@ object Type { numeric || string || array || + vector || struct } /** Compute the common type for a pair of types */ @@ -623,6 +689,21 @@ object Type { override def boolean(a: Analysis) = Some(1) + override def vector(a: Analysis, t: Type.Vector) = { + val n = BigInt(t.anonVector.maxSize.get) + for { + eltSize <- ty(a, t.anonVector.eltType) + prefixSize <- { + val prefixType = t.sizePrefixType.getOrElse { + val fwSizeStoreSymbol = a.frameworkDefinitions.typeMap("FwSizeStoreType") + a.typeMap(fwSizeStoreSymbol.getNodeId) + } + ty(a, prefixType) + } + } + yield prefixSize + n * eltSize + } + override def enumeration(a: Analysis, t: Type.Enum) = ty(a, t.repType) diff --git a/compiler/lib/src/main/scala/analysis/Semantics/TypeVisitor.scala b/compiler/lib/src/main/scala/analysis/Semantics/TypeVisitor.scala index db34714a8..53ad6713c 100644 --- a/compiler/lib/src/main/scala/analysis/Semantics/TypeVisitor.scala +++ b/compiler/lib/src/main/scala/analysis/Semantics/TypeVisitor.scala @@ -15,6 +15,8 @@ trait TypeVisitor { def anonStruct(in: In, t: Type.AnonStruct): Out = default(in, t) + def anonVector(in: In, t: Type.AnonVector): Out = default(in, t) + def array(in: In, t: Type.Array): Out = default(in, t) def boolean(in: In): Out = default(in, Type.Boolean) @@ -33,6 +35,8 @@ trait TypeVisitor { def struct(in: In, t: Type.Struct): Out = default(in, t) + def vector(in: In, t: Type.Vector): Out = default(in, t) + def ty(in: In, t: Type): Out = matchType(in, t) final def matchType(in: In, t: Type): Out = @@ -41,6 +45,7 @@ trait TypeVisitor { case t : Type.AliasType => aliasType(in, t) case t : Type.AnonArray => anonArray(in, t) case t : Type.AnonStruct => anonStruct(in, t) + case t : Type.AnonVector => anonVector(in, t) case t : Type.Array => array(in, t) case Type.Boolean => boolean(in) case t : Type.Enum => enumeration(in, t) @@ -49,5 +54,6 @@ trait TypeVisitor { case t : Type.PrimitiveInt => primitiveInt(in, t) case t : Type.String => string(in, t) case t : Type.Struct => struct(in, t) + case t : Type.Vector => vector(in, t) } } diff --git a/compiler/lib/src/main/scala/analysis/Semantics/Value.scala b/compiler/lib/src/main/scala/analysis/Semantics/Value.scala index 1bb2fffcb..7a31db07a 100644 --- a/compiler/lib/src/main/scala/analysis/Semantics/Value.scala +++ b/compiler/lib/src/main/scala/analysis/Semantics/Value.scala @@ -334,10 +334,27 @@ object Value { yield Array(anonArray, arrayType) } + def convertToVector(vectorType: Type.Vector): Option[Value.Vector] = { + def convertElements(in: List[Value], t: Type, out: List[Value]): Option[List[Value]] = + in match { + case Nil => Some(out.reverse) + case head :: tail => head.convertToType(t.getUnderlyingType) match { + case Some(v) => convertElements(tail, t.getUnderlyingType, v :: out) + case None => None + } + } + val Type.AnonVector(maxSize, eltType) = vectorType.anonVector + if (Type.Vector.maxSizeAllows(Some(elements.size), maxSize)) + for (elements <- convertElements(elements, eltType, Nil)) + yield Vector(AnonArray(elements), vectorType) + else None + } + override def convertToDistinctType(t: Type) = t.getUnderlyingType match { case anonArrayType : Type.AnonArray => convertToAnonArray(anonArrayType) case arrayType : Type.Array => convertToArray(arrayType) + case vectorType : Type.Vector => convertToVector(vectorType) case _ => None } @@ -367,10 +384,14 @@ object Value { def convertToArray(arrayType: Type.Array): Option[Value.Array] = anonArray.convertToArray(arrayType) + def convertToVector(vectorType: Type.Vector): Option[Value.Vector] = + anonArray.convertToVector(vectorType) + override def convertToDistinctType(t: Type) = t.getUnderlyingType match { case anonArrayType : Type.AnonArray => convertToAnonArray(anonArrayType) case arrayType : Type.Array => convertToArray(arrayType) + case vectorType : Type.Vector => convertToVector(vectorType) case _ => None } @@ -382,6 +403,26 @@ object Value { } + /** Vector values */ + case class Vector(anonArray: AnonArray, t: Type.Vector) extends Value { + + def convertToVector(vectorType: Type.Vector): Option[Value.Vector] = + anonArray.convertToVector(vectorType) + + override def convertToDistinctType(t: Type) = + t.getUnderlyingType match { + case vectorType : Type.Vector => convertToVector(vectorType) + case _ => None + } + + override def getType = t + + override def toString = anonArray.toString ++ ": " ++ t.node._2.data.name + + override def truncate: Vector = Vector(anonArray.truncate, t) + + } + /** Enum constant values */ case class EnumConstant(value: (Name.Unqualified, BigInt), t: Type.Enum) extends Value { diff --git a/compiler/lib/src/main/scala/analysis/Semantics/ValueVisitor.scala b/compiler/lib/src/main/scala/analysis/Semantics/ValueVisitor.scala index 6647fd729..99e4a1eef 100644 --- a/compiler/lib/src/main/scala/analysis/Semantics/ValueVisitor.scala +++ b/compiler/lib/src/main/scala/analysis/Semantics/ValueVisitor.scala @@ -31,6 +31,8 @@ trait ValueVisitor { def struct(in: In, v: Value.Struct): Out = default(in, v) + def vector(in: In, v: Value.Vector): Out = default(in, v) + def value(in: In, v: Value): Out = matchValue(in, v) final def matchValue(in: In, v: Value): Out = { @@ -46,6 +48,7 @@ trait ValueVisitor { case v : Value.EnumConstant => enumConstant(in, v) case v : Value.AnonStruct => anonStruct(in, v) case v : Value.Struct => struct(in, v) + case v : Value.Vector => vector(in, v) } } diff --git a/compiler/lib/src/main/scala/analysis/UsedSymbols.scala b/compiler/lib/src/main/scala/analysis/UsedSymbols.scala index dea479774..079510d41 100644 --- a/compiler/lib/src/main/scala/analysis/UsedSymbols.scala +++ b/compiler/lib/src/main/scala/analysis/UsedSymbols.scala @@ -118,6 +118,7 @@ object UsedSymbols extends UseAnalyzer { case Symbol.Struct(node) => defStructAnnotatedNode(a1, node) case Symbol.System(node) => defSystemAnnotatedNode(a1, node) case Symbol.Topology(node) => defTopologyAnnotatedNode(a1, node) + case Symbol.Vector(node) => defVectorAnnotatedNode(a1, node) } a2.usedSymbolSet.flatMap(resolveNode) + resolveEnumConstant(s) } diff --git a/compiler/lib/src/main/scala/codegen/CppWriter/CppWriterState.scala b/compiler/lib/src/main/scala/codegen/CppWriter/CppWriterState.scala index cb9798695..2b8c811af 100644 --- a/compiler/lib/src/main/scala/codegen/CppWriter/CppWriterState.scala +++ b/compiler/lib/src/main/scala/codegen/CppWriter/CppWriterState.scala @@ -178,6 +178,9 @@ case class CppWriterState( case _: Symbol.Struct => List( getIncludePath(sym, ComputeCppFiles.FileNames.getStruct(name)) ) + case _: Symbol.Vector => + // Code generation for vector types is not yet implemented + throw new InternalError("code generation for vector types is not yet implemented") case _: Symbol.Topology => List( getIncludePath(sym, ComputeCppFiles.FileNames.getTopology(name)) ) diff --git a/compiler/lib/src/main/scala/codegen/JsonEncoder/AnalysisJsonEncoder.scala b/compiler/lib/src/main/scala/codegen/JsonEncoder/AnalysisJsonEncoder.scala index ffa734f57..560111304 100644 --- a/compiler/lib/src/main/scala/codegen/JsonEncoder/AnalysisJsonEncoder.scala +++ b/compiler/lib/src/main/scala/codegen/JsonEncoder/AnalysisJsonEncoder.scala @@ -185,6 +185,9 @@ object AnalysisJsonEncoder extends JsonEncoder{ private implicit val valueStructEncoder: Encoder[Value.Struct] = io.circe.generic.semiauto.deriveEncoder[Value.Struct] + private implicit val valueVectorEncoder: Encoder[Value.Vector] = + io.circe.generic.semiauto.deriveEncoder[Value.Vector] + // ---------------------------------------------------------------------- // Methods for converting Scala maps to JSON maps // We use this conversion when the keys can be converted to strings diff --git a/compiler/lib/src/main/scala/codegen/LocateDefsFppWriter.scala b/compiler/lib/src/main/scala/codegen/LocateDefsFppWriter.scala index 433f45f51..f428602d4 100644 --- a/compiler/lib/src/main/scala/codegen/LocateDefsFppWriter.scala +++ b/compiler/lib/src/main/scala/codegen/LocateDefsFppWriter.scala @@ -152,6 +152,15 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils { writeSpecLoc(s, Ast.SpecLoc.Instance, data.name, node) } + override def defVectorAnnotatedNode( + s: State, + aNode: Ast.Annotated[AstNode[Ast.DefVector]] + ) = { + val (_, node, _) = aNode + val data = node.data + writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node, data.isDictionaryDef) + } + override def transUnit(s: State, tu: Ast.TransUnit) = tu.members.flatMap(matchModuleMember(s, _)) diff --git a/compiler/lib/src/test/scala/semantics/TypeSpec.scala b/compiler/lib/src/test/scala/semantics/TypeSpec.scala index d3d640af2..8915384dc 100644 --- a/compiler/lib/src/test/scala/semantics/TypeSpec.scala +++ b/compiler/lib/src/test/scala/semantics/TypeSpec.scala @@ -17,6 +17,7 @@ class TypeSpec extends AnyWordSpec { duplicate(defaultEnum), duplicate(defaultStruct), duplicate(defaultAliasType), + duplicate(defaultVector), duplicate(Boolean), duplicate(F32), duplicate(F64), @@ -35,14 +36,18 @@ class TypeSpec extends AnyWordSpec { (enumeration("E0", I32, 0), enumeration("E1", U32, 1)), (array("A0", AnonArray(None, I32), 0), array("A1", AnonArray(None, U32), 1)), (struct("S0", AnonStruct(Map()), 0), struct("S1", AnonStruct(Map()), 1)), + (vector("V0", AnonVector(None, I32), None, 0), vector("V1", AnonVector(None, U32), None, 1)), (array("A", AnonArray(None, I32), 0), struct("S0", AnonStruct(Map()), 1)), (defaultAbsType, defaultEnum), (defaultArray, defaultStruct), + (defaultArray, defaultVector), + (defaultVector, defaultStruct), (Boolean,String(None)), duplicate(String(None)), (F32,F64), (I8,U32), duplicate(AnonArray(None, I32)), + duplicate(AnonVector(None, I32)), duplicate(AnonStruct(Map())), (aliasType("TAliasU32", U32, 0), U32), (aliasType("AliasE", enumeration("E", I32, 0), 1), enumeration("E", I32, 0)) @@ -73,6 +78,19 @@ class TypeSpec extends AnyWordSpec { String(None) -> AnonArray(None, String(None)), enumeration("E") -> AnonArray(None, I32), AnonArray(Some(3), I32) -> AnonArray(Some(3), AnonArray(Some(3), I32)), + AnonArray(Some(3), I32) -> AnonVector(Some(3), I32), + AnonArray(Some(2), I32) -> AnonVector(Some(3), I32), + AnonArray(Some(3), I32) -> AnonVector(None, I32), + AnonArray(None, I32) -> AnonVector(Some(3), I32), + AnonArray(Some(3), enumeration("E")) -> AnonVector(Some(3), I32), + AnonArray(Some(3), I32) -> AnonVector(Some(3), U32), + duplicate(AnonVector(Some(3), I32)), + AnonVector(Some(2), I32) -> AnonVector(Some(3), I32), + AnonVector(None, enumeration("E")) -> AnonVector(None, I32), + AnonArray(Some(3), AnonArray(Some(2), I32)) -> AnonVector(Some(3), AnonVector(Some(2), I32)), + vector("V", AnonVector(Some(3), I32), None, 0) -> AnonVector(Some(3), U32), + array("A", AnonArray(Some(2), I32), 0) -> vector("V", AnonVector(Some(3), U32), None, 1), + vector("V0", AnonVector(Some(3), I32), None, 0) -> vector("V1", AnonVector(Some(3), U32), None, 1), duplicate(AnonStruct(Map("x" -> I32))), AnonStruct(Map("x" -> I32)) -> AnonStruct(Map("x" -> AnonArray(None, I32))), AnonStruct(Map("x" -> I32)) -> AnonStruct(Map("x" -> I32, "y" -> I32)), @@ -96,6 +114,16 @@ class TypeSpec extends AnyWordSpec { array("A", AnonArray(None, I32)) -> AnonArray(None, String(None)), array("A0", AnonArray(None, I32), 0) -> array("A1", AnonArray(None, String(None)), 1), String(None) -> AnonArray(None, I32), + I32 -> AnonVector(None, I32), + Boolean -> AnonVector(None, Boolean), + enumeration("E") -> AnonVector(None, I32), + String(None) -> AnonVector(None, String(None)), + AnonArray(Some(4), I32) -> AnonVector(Some(3), I32), + AnonVector(Some(4), I32) -> AnonVector(Some(3), I32), + AnonArray(Some(3), I32) -> AnonVector(Some(3), String(None)), + AnonVector(None, I32) -> AnonArray(None, I32), + vector("V", AnonVector(Some(3), I32), None, 0) -> array("A", AnonArray(Some(3), I32), 1), + AnonVector(None, I32) -> AnonStruct(Map()), AnonStruct(Map("x" -> I32)) -> AnonStruct(Map("x" -> String(None))), AnonStruct(Map("x" -> I32)) -> AnonStruct(Map("y" -> I32)), struct("S", AnonStruct(Map("x" -> I32))) -> AnonStruct(Map("x" -> String(None))), @@ -124,6 +152,7 @@ class TypeSpec extends AnyWordSpec { duplicate(defaultArray) -> defaultArray, duplicate(defaultEnum) -> defaultEnum, duplicate(defaultStruct) -> defaultStruct, + duplicate(defaultVector) -> defaultVector, (I32, I8) -> Integer, (F32, F64) -> F64, (I32, F64) -> F64, @@ -205,6 +234,12 @@ class TypeSpec extends AnyWordSpec { (AnonStruct(Map()), defaultArray), (defaultStruct, AnonArray(None, I32)), (AnonArray(None,I32), defaultStruct), + (defaultVector, defaultArray), + (defaultArray, defaultVector), + (defaultVector, defaultStruct), + (vector("V0", AnonVector(None, I32), None, 0), vector("V1", AnonVector(None, I32), None, 1)), + (AnonVector(Some(3), I32), AnonVector(Some(3), I32)), + (defaultVector, AnonVector(None, I32)), ) allowedPairs.foreach { pair => s"resolve ${pair._1} to ${pair._2}" in @@ -225,15 +260,19 @@ class TypeSpec extends AnyWordSpec { defaultEnum, defaultArray, defaultStruct, + defaultVector, array("A1", AnonArray(None, array("A2", AnonArray(None, I32)))), + vector("V1", AnonVector(None, vector("V2", AnonVector(None, I32)))), struct("S1", AnonStruct(Map("x" -> I32))) ) val notDisplayable = List( Integer, AnonArray(None, I32), + AnonVector(None, I32), AnonStruct(Map()), defaultAbsType, array("A3", AnonArray(None, defaultAbsType)), + vector("V3", AnonVector(None, defaultAbsType)), array("A4", AnonArray(None, array("A5", AnonArray(None, defaultAbsType)))), struct("S2", AnonStruct(Map("x" -> defaultAbsType))), struct( @@ -320,6 +359,20 @@ class TypeSpec extends AnyWordSpec { assert(SerializedSize.ty(a, array2) == Some(48)) } + "compute the size of vectors" in { + // Explicit U16 size-prefix type: 2 bytes prefix + 3 * 2 bytes = 8 + // (matches the sizeof(V) example in the specification) + val vectorExplicitPrefix = vector("VecW", AnonVector(Some(3), U16), Some(U16), 20) + assert(SerializedSize.ty(a, vectorExplicitPrefix) == Some(8)) + // Omitted size-prefix type: uses FwSizeStoreType (U16 = 2 bytes) + // 2 bytes prefix + 3 * 1 byte = 5 + val vectorDefaultPrefix = vector("VecV", AnonVector(Some(3), U8), None, 21) + assert(SerializedSize.ty(a, vectorDefaultPrefix) == Some(5)) + // A vector of an element type with no serialized size has no size + val vectorNoSize = vector("VecNo", AnonVector(Some(3), defaultAbsType), None, 22) + assert(SerializedSize.ty(a, vectorNoSize) == None) + } + "compute the size of enums" in { assert(SerializedSize.ty(a, enum1) == Some(2)) } diff --git a/compiler/lib/src/test/scala/semantics/Types.scala b/compiler/lib/src/test/scala/semantics/Types.scala index 9f270992b..5ecafb827 100644 --- a/compiler/lib/src/test/scala/semantics/Types.scala +++ b/compiler/lib/src/test/scala/semantics/Types.scala @@ -53,10 +53,24 @@ object Types { Struct(anode, anonStruct, None, sizes) } + def vector( + name: Ast.Ident, + anonVector: AnonVector = AnonVector(None, U32), + sizePrefixType: Option[Type] = None, + id: AstNode.Id = 0 + ): Vector = { + val size = AstNode.create(Ast.ExprLiteralInt("1")) + val eltType = AstNode.create(Ast.TypeNameInt(Ast.U32)) + val d = Ast.DefVector(name, size, None, eltType, None, None, false) + val anode = annotatedNode(d, id) + Vector(anode, anonVector, sizePrefixType) + } + val defaultAbsType: AbsType = absType("T", 0) val defaultArray: Array = array("A", AnonArray(None, I32), 1) val defaultEnum: Enum = enumeration("E", I32, 2) val defaultStruct: Struct = struct("S", AnonStruct(Map()), 3) val defaultAliasType: AliasType = aliasType("TAlias", defaultAbsType, 4) + val defaultVector: Vector = vector("V", AnonVector(None, I32), None, 5) } diff --git a/compiler/lib/src/test/scala/semantics/ValueSpec.scala b/compiler/lib/src/test/scala/semantics/ValueSpec.scala index ce0fe8c43..a7608fc2d 100644 --- a/compiler/lib/src/test/scala/semantics/ValueSpec.scala +++ b/compiler/lib/src/test/scala/semantics/ValueSpec.scala @@ -30,6 +30,8 @@ class ValueSpec extends AnyWordSpec { (enumeration, enumType), (anonStruct, anonStructType), (struct, structType), + (vector, vectorType), + (emptyVector, vectorType), ) pairs.foreach { pair => s"evaluate ${pair._1} to ${pair._2}" in @@ -51,6 +53,7 @@ class ValueSpec extends AnyWordSpec { (createI32(1), array, None), (createI32(1), anonStruct, None), (createI32(1), struct, None), + (createI32(1), vector, None), (String("abc"), String("def"), Some(String("abcdef"))) ) triples.foreach { @@ -194,6 +197,7 @@ class ValueSpec extends AnyWordSpec { (defaultAnonArray3U32, false), (struct, false), (anonStruct, false), + (vector, false), ) pairs.foreach { pair => s"evaluate ${pair._1} to ${pair._2}" in @@ -235,6 +239,13 @@ class ValueSpec extends AnyWordSpec { Type.AnonStruct(Map("a" -> Type.U32)), Some(AnonStruct(Map("a" -> defaultU32))) ), + (createAnonArray(2, createU8(1)), vectorType, Some(vector)), + (createAnonArray(2, createI32(1)), vectorType, Some(vector)), + (createAnonArray(4, createU8(1)), vectorType, None), + (createI32(1), vectorType, None), + (vector, vectorType2, Some(Vector(AnonArray(List.fill(2)(createU16(1))), vectorType2))), + (array, vectorType2, Some(Vector(AnonArray(List.fill(3)(createU16(0))), vectorType2))), + (vector, arrayType, None), ) triples.foreach { triple => s"evaluate ${triple._1} and ${triple._2} to ${triple._3}" in @@ -270,6 +281,10 @@ class ValueSpec extends AnyWordSpec { (createAnonArray(3, createU8(257)), createAnonArray(3, createU8(1))), (createAnonArray(3, createI8(257)), createAnonArray(3, createI8(1))), (createAnonArray(3, createU8(-1)), createAnonArray(3, createU8(255))), + ( + Vector(AnonArray(List.fill(2)(createU8(256))), vectorType), + Vector(AnonArray(List.fill(2)(createU8(0))), vectorType) + ), ) pairs.foreach { pair => s"evaluate ${pair._1} to ${pair._2}" in diff --git a/compiler/lib/src/test/scala/semantics/Values.scala b/compiler/lib/src/test/scala/semantics/Values.scala index dc97bd80a..bd0cfc934 100644 --- a/compiler/lib/src/test/scala/semantics/Values.scala +++ b/compiler/lib/src/test/scala/semantics/Values.scala @@ -53,4 +53,9 @@ object Values { val structType: Type.Struct = Types.struct("S", anonStructType, 3) val struct: Struct = Struct(anonStruct, structType) + val vectorType: Type.Vector = Types.vector("V", Type.AnonVector(Some(3), Type.U8), None, 6) + val vector: Vector = Vector(AnonArray(List.fill(2)(createU8(1))), vectorType) + val emptyVector: Vector = Vector(AnonArray(Nil), vectorType) + val vectorType2: Type.Vector = Types.vector("V2", Type.AnonVector(Some(5), Type.U16), None, 7) + } diff --git a/compiler/tools/fpp-check/test/vector/clean b/compiler/tools/fpp-check/test/vector/clean new file mode 100755 index 000000000..32e49663c --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/clean @@ -0,0 +1,6 @@ +#!/bin/sh -e + +. ../../../../scripts/utils.sh + +clean +rm -f default-tests.sh default-update-ref.sh diff --git a/compiler/tools/fpp-check/test/vector/cycle.fpp b/compiler/tools/fpp-check/test/vector/cycle.fpp new file mode 100644 index 000000000..c6e11c2eb --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/cycle.fpp @@ -0,0 +1,4 @@ +type FwSizeStoreType = U16 + +# A vector may not use itself as its element type +vector V = [size 3] V diff --git a/compiler/tools/fpp-check/test/vector/cycle.ref.txt b/compiler/tools/fpp-check/test/vector/cycle.ref.txt new file mode 100644 index 000000000..5b9401051 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/cycle.ref.txt @@ -0,0 +1,6 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/cycle.fpp:4.1 +vector V = [size 3] V +^ +error: encountered a use-def cycle: + use V at [ local path prefix ]/compiler/tools/fpp-check/test/vector/cycle.fpp:4.21 refers to definition V at [ local path prefix ]/compiler/tools/fpp-check/test/vector/cycle.fpp:4.1 diff --git a/compiler/tools/fpp-check/test/vector/default_ok.fpp b/compiler/tools/fpp-check/test/vector/default_ok.fpp new file mode 100644 index 000000000..a46d7f9cf --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/default_ok.fpp @@ -0,0 +1,11 @@ +type FwSizeStoreType = U16 + +vector V = [size 4] U8 default [ 1, 2 ] + +passive component C { + vector V = [size 4] U8 default [ 1, 2 ] +} + +module M { + vector V = [size 4] U8 default [ 1, 2 ] +} diff --git a/compiler/tools/fpp-check/test/vector/default_ok.ref.txt b/compiler/tools/fpp-check/test/vector/default_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/default_too_long.fpp b/compiler/tools/fpp-check/test/vector/default_too_long.fpp new file mode 100644 index 000000000..b9a85e330 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/default_too_long.fpp @@ -0,0 +1,4 @@ +type FwSizeStoreType = U16 + +# The length of the default value must not exceed the maximum size +vector V = [size 2] U8 default [ 1, 2, 3 ] diff --git a/compiler/tools/fpp-check/test/vector/default_too_long.ref.txt b/compiler/tools/fpp-check/test/vector/default_too_long.ref.txt new file mode 100644 index 000000000..7b2c719f9 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/default_too_long.ref.txt @@ -0,0 +1,5 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/default_too_long.fpp:4.32 +vector V = [size 2] U8 default [ 1, 2, 3 ] + ^ +error: cannot convert [3] Integer to vector V diff --git a/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.fpp b/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.fpp new file mode 100644 index 000000000..dbf349fa9 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.fpp @@ -0,0 +1,4 @@ +type FwSizeStoreType = U16 +type T + +dictionary vector V = [size 3] T diff --git a/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.ref.txt b/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.ref.txt new file mode 100644 index 000000000..663a15827 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.ref.txt @@ -0,0 +1,15 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.fpp:4.1 +dictionary vector V = [size 3] T +^ +error: dictionary type is not displayable + +[ local path prefix ]/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.fpp:4.32 +dictionary vector V = [size 3] T + ^ +because this type is not displayable + +[ local path prefix ]/compiler/tools/fpp-check/test/vector/dictionary_not_displayable.fpp:2.1 +type T +^ +Type is defined here diff --git a/compiler/tools/fpp-check/test/vector/dictionary_ok.fpp b/compiler/tools/fpp-check/test/vector/dictionary_ok.fpp new file mode 100644 index 000000000..069c98961 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/dictionary_ok.fpp @@ -0,0 +1,3 @@ +type FwSizeStoreType = U16 + +dictionary vector V = [size 3] U8 diff --git a/compiler/tools/fpp-check/test/vector/dictionary_ok.ref.txt b/compiler/tools/fpp-check/test/vector/dictionary_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/enum_element_ok.fpp b/compiler/tools/fpp-check/test/vector/enum_element_ok.fpp new file mode 100644 index 000000000..326c87e55 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/enum_element_ok.fpp @@ -0,0 +1,5 @@ +type FwSizeStoreType = U16 + +enum E { X, Y } + +vector V = [size 3] E default [ E.X, E.Y ] diff --git a/compiler/tools/fpp-check/test/vector/enum_element_ok.ref.txt b/compiler/tools/fpp-check/test/vector/enum_element_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/format_ok.fpp b/compiler/tools/fpp-check/test/vector/format_ok.fpp new file mode 100644 index 000000000..1a4b96a29 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/format_ok.fpp @@ -0,0 +1,4 @@ +type FwSizeStoreType = U16 + +# The format string is applied to each element; it has one argument +vector V = [size 3] U8 format "elt {}" diff --git a/compiler/tools/fpp-check/test/vector/format_ok.ref.txt b/compiler/tools/fpp-check/test/vector/format_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/format_too_many_fields.fpp b/compiler/tools/fpp-check/test/vector/format_too_many_fields.fpp new file mode 100644 index 000000000..e67c45c15 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/format_too_many_fields.fpp @@ -0,0 +1,4 @@ +type FwSizeStoreType = U16 + +# There is one argument to the format string, which is a vector element +vector V = [size 3] U8 format "{} {}" diff --git a/compiler/tools/fpp-check/test/vector/format_too_many_fields.ref.txt b/compiler/tools/fpp-check/test/vector/format_too_many_fields.ref.txt new file mode 100644 index 000000000..71df757f8 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/format_too_many_fields.ref.txt @@ -0,0 +1,5 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/format_too_many_fields.fpp:4.31 +vector V = [size 3] U8 format "{} {}" + ^ +error: invalid format string: too many replacement fields diff --git a/compiler/tools/fpp-check/test/vector/invalid_size.fpp b/compiler/tools/fpp-check/test/vector/invalid_size.fpp new file mode 100644 index 000000000..9bb111b31 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/invalid_size.fpp @@ -0,0 +1,2 @@ +# The maximum size must be greater than zero +vector V = [U8 size 0] U8 diff --git a/compiler/tools/fpp-check/test/vector/invalid_size.ref.txt b/compiler/tools/fpp-check/test/vector/invalid_size.ref.txt new file mode 100644 index 000000000..f3ce735a4 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/invalid_size.ref.txt @@ -0,0 +1,6 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/invalid_size.fpp:2.21 +vector V = [U8 size 0] U8 + ^ +error: invalid array size 0 +note: size must be greater than zero diff --git a/compiler/tools/fpp-check/test/vector/missing_size_store_type.fpp b/compiler/tools/fpp-check/test/vector/missing_size_store_type.fpp new file mode 100644 index 000000000..c96bcf674 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/missing_size_store_type.fpp @@ -0,0 +1,3 @@ +# Omitting the size-prefix type is an implied use of FwSizeStoreType, +# which must be defined +vector V = [size 3] U8 diff --git a/compiler/tools/fpp-check/test/vector/missing_size_store_type.ref.txt b/compiler/tools/fpp-check/test/vector/missing_size_store_type.ref.txt new file mode 100644 index 000000000..a53772fb8 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/missing_size_store_type.ref.txt @@ -0,0 +1,8 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/missing_size_store_type.fpp:3.1 +vector V = [size 3] U8 +^ +error: symbol FwSizeStoreType is not defined +note: looking for a type here +note: the symbol FwSizeStoreType has an implied use at the point of the error +note: use of a vector type without a size-prefix type requires this definition diff --git a/compiler/tools/fpp-check/test/vector/nested_ok.fpp b/compiler/tools/fpp-check/test/vector/nested_ok.fpp new file mode 100644 index 000000000..327c259de --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/nested_ok.fpp @@ -0,0 +1,6 @@ +type FwSizeStoreType = U16 + +# A vector of vectors, and an array of vectors +vector Inner = [size 2] U8 +vector Outer = [size 3] Inner default [ [ 1, 2 ], [ 3, 4 ] ] +array A = [2] Inner default [ [ 1 ], [ 1 ] ] diff --git a/compiler/tools/fpp-check/test/vector/nested_ok.ref.txt b/compiler/tools/fpp-check/test/vector/nested_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/no_default_ok.fpp b/compiler/tools/fpp-check/test/vector/no_default_ok.fpp new file mode 100644 index 000000000..3ad7a7ba4 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/no_default_ok.fpp @@ -0,0 +1,11 @@ +type FwSizeStoreType = U16 + +vector V = [size 4] U8 + +passive component C { + vector V = [size 4] U8 +} + +module M { + vector V = [size 4] U8 +} diff --git a/compiler/tools/fpp-check/test/vector/no_default_ok.ref.txt b/compiler/tools/fpp-check/test/vector/no_default_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/run b/compiler/tools/fpp-check/test/vector/run new file mode 100755 index 000000000..92816cad0 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/run @@ -0,0 +1,4 @@ +#!/bin/sh + +export LOCAL_PATH_PREFIX=`cd ../../../../..; echo $PWD` +../run-script diff --git a/compiler/tools/fpp-check/test/vector/scalar_default.fpp b/compiler/tools/fpp-check/test/vector/scalar_default.fpp new file mode 100644 index 000000000..5fef15b91 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/scalar_default.fpp @@ -0,0 +1,4 @@ +type FwSizeStoreType = U16 + +# A vector is not filled from a single scalar value, unlike an array +vector V = [size 3] U8 default 1 diff --git a/compiler/tools/fpp-check/test/vector/scalar_default.ref.txt b/compiler/tools/fpp-check/test/vector/scalar_default.ref.txt new file mode 100644 index 000000000..c9cb1807d --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/scalar_default.ref.txt @@ -0,0 +1,5 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/scalar_default.fpp:4.32 +vector V = [size 3] U8 default 1 + ^ +error: cannot convert Integer to vector V diff --git a/compiler/tools/fpp-check/test/vector/size_prefix_not_integer.fpp b/compiler/tools/fpp-check/test/vector/size_prefix_not_integer.fpp new file mode 100644 index 000000000..b0eb8fa7b --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/size_prefix_not_integer.fpp @@ -0,0 +1,2 @@ +# The size-prefix type must be a primitive integer type +vector V = [F32 size 3] U8 diff --git a/compiler/tools/fpp-check/test/vector/size_prefix_not_integer.ref.txt b/compiler/tools/fpp-check/test/vector/size_prefix_not_integer.ref.txt new file mode 100644 index 000000000..925deb41b --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/size_prefix_not_integer.ref.txt @@ -0,0 +1,5 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/size_prefix_not_integer.fpp:2.13 +vector V = [F32 size 3] U8 + ^ +error: vector size-prefix type must be an unsigned primitive integer type diff --git a/compiler/tools/fpp-check/test/vector/size_prefix_ok.fpp b/compiler/tools/fpp-check/test/vector/size_prefix_ok.fpp new file mode 100644 index 000000000..efa45d88b --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/size_prefix_ok.fpp @@ -0,0 +1,5 @@ +# An explicit unsigned primitive integer size-prefix type, and an alias to one +type MyU8 = U8 + +vector V = [U16 size 3] U8 +vector W = [MyU8 size 3] U8 diff --git a/compiler/tools/fpp-check/test/vector/size_prefix_ok.ref.txt b/compiler/tools/fpp-check/test/vector/size_prefix_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/size_prefix_signed.fpp b/compiler/tools/fpp-check/test/vector/size_prefix_signed.fpp new file mode 100644 index 000000000..646621c25 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/size_prefix_signed.fpp @@ -0,0 +1,2 @@ +# The size-prefix type must be unsigned +vector V = [I16 size 3] U8 diff --git a/compiler/tools/fpp-check/test/vector/size_prefix_signed.ref.txt b/compiler/tools/fpp-check/test/vector/size_prefix_signed.ref.txt new file mode 100644 index 000000000..adbae7849 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/size_prefix_signed.ref.txt @@ -0,0 +1,5 @@ +fpp-check +[ local path prefix ]/compiler/tools/fpp-check/test/vector/size_prefix_signed.fpp:2.13 +vector V = [I16 size 3] U8 + ^ +error: vector size-prefix type must be an unsigned primitive integer type diff --git a/compiler/tools/fpp-check/test/vector/sizeof_ok.fpp b/compiler/tools/fpp-check/test/vector/sizeof_ok.fpp new file mode 100644 index 000000000..47e6f2027 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/sizeof_ok.fpp @@ -0,0 +1,9 @@ +type FwSizeStoreType = U16 + +# Implicit size-prefix type (FwSizeStoreType = U16): 2 + 3 * 1 = 5 +vector V = [size 3] U8 +# Explicit U16 size-prefix type: 2 + 3 * 2 = 8 +vector W = [U16 size 3] U16 + +constant a = sizeof(V) +constant b = sizeof(W) diff --git a/compiler/tools/fpp-check/test/vector/sizeof_ok.ref.txt b/compiler/tools/fpp-check/test/vector/sizeof_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/struct_member_ok.fpp b/compiler/tools/fpp-check/test/vector/struct_member_ok.fpp new file mode 100644 index 000000000..038219018 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/struct_member_ok.fpp @@ -0,0 +1,4 @@ +type FwSizeStoreType = U16 + +vector V = [size 3] U8 +struct S { v: V } diff --git a/compiler/tools/fpp-check/test/vector/struct_member_ok.ref.txt b/compiler/tools/fpp-check/test/vector/struct_member_ok.ref.txt new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tools/fpp-check/test/vector/tests.sh b/compiler/tools/fpp-check/test/vector/tests.sh new file mode 100644 index 000000000..4e9aa3904 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/tests.sh @@ -0,0 +1,20 @@ +tests=" +default_ok +no_default_ok +size_prefix_ok +enum_element_ok +nested_ok +sizeof_ok +format_ok +struct_member_ok +dictionary_ok +default_too_long +invalid_size +size_prefix_signed +size_prefix_not_integer +missing_size_store_type +scalar_default +dictionary_not_displayable +format_too_many_fields +cycle +" diff --git a/compiler/tools/fpp-check/test/vector/update-ref b/compiler/tools/fpp-check/test/vector/update-ref new file mode 100755 index 000000000..0f11071e7 --- /dev/null +++ b/compiler/tools/fpp-check/test/vector/update-ref @@ -0,0 +1,4 @@ +#!/bin/sh + +export LOCAL_PATH_PREFIX=`cd ../../../../..; echo $PWD` +../update-ref-script diff --git a/compiler/tools/fpp-depend/test/def_vector.fpp b/compiler/tools/fpp-depend/test/def_vector.fpp new file mode 100644 index 000000000..43d773d04 --- /dev/null +++ b/compiler/tools/fpp-depend/test/def_vector.fpp @@ -0,0 +1,12 @@ +locate constant a at "a.fpp" +locate constant b at "b.fpp" +locate dictionary constant d at "d.fpp" + +locate type T at "T.fpp" +locate type Tp at "Tp.fpp" +locate type FwSizeStoreType at "FwSizeStoreType.fpp" +locate dictionary type T2 at "T2.fpp" + +vector V1 = [Tp size a] T default b +vector V2 = [size a] T +dictionary vector V3 = [size d] T2 diff --git a/compiler/tools/fpp-depend/test/def_vector.ref.txt b/compiler/tools/fpp-depend/test/def_vector.ref.txt new file mode 100644 index 000000000..0b9c1e533 --- /dev/null +++ b/compiler/tools/fpp-depend/test/def_vector.ref.txt @@ -0,0 +1,7 @@ +[ local path prefix ]/compiler/tools/fpp-depend/test/FwSizeStoreType.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/Tp.fpp +[ local path prefix ]/compiler/tools/fpp-depend/test/a.fpp +[ local path prefix ]/compiler/tools/fpp-depend/test/b.fpp +[ local path prefix ]/compiler/tools/fpp-depend/test/d.fpp diff --git a/compiler/tools/fpp-depend/test/tests.sh b/compiler/tools/fpp-depend/test/tests.sh index 41589ef4c..d6c44683d 100644 --- a/compiler/tools/fpp-depend/test/tests.sh +++ b/compiler/tools/fpp-depend/test/tests.sh @@ -9,6 +9,7 @@ def_port def_state_machine def_struct def_system +def_vector dictionary dictionary_no_deployment_top direct diff --git a/compiler/tools/fpp-locate-defs/test/defs.ref.txt b/compiler/tools/fpp-locate-defs/test/defs.ref.txt index 5ebd11f28..f4f228b50 100644 --- a/compiler/tools/fpp-locate-defs/test/defs.ref.txt +++ b/compiler/tools/fpp-locate-defs/test/defs.ref.txt @@ -9,6 +9,7 @@ locate constant a at "defs/defs-1.fpp" locate dictionary constant a2 at "defs/defs-1.fpp" locate dictionary type Alias2 at "defs/defs-1.fpp" locate dictionary type C.A2 at "defs/defs-1.fpp" +locate dictionary type C.V2 at "defs/defs-1.fpp" locate dictionary type M.C.E2 at "defs/defs-2.fpp" locate dictionary type M.C.S2 at "defs/defs-2.fpp" locate instance M.T at "defs/defs-2.fpp" @@ -30,6 +31,7 @@ locate type C.Alias at "defs/defs-1.fpp" locate type C.E at "defs/defs-1.fpp" locate type C.S at "defs/defs-1.fpp" locate type C.T at "defs/defs-1.fpp" +locate type C.V at "defs/defs-1.fpp" locate type E at "defs/defs-1.fpp" locate type M.A at "defs/defs-2.fpp" locate type M.Alias at "defs/defs-2.fpp" @@ -38,6 +40,7 @@ locate type M.C.Alias at "defs/defs-2.fpp" locate type M.C.E at "defs/defs-2.fpp" locate type M.C.S at "defs/defs-2.fpp" locate type M.C.T at "defs/defs-2.fpp" +locate type M.C.V at "defs/defs-2.fpp" locate type M.E at "defs/defs-2.fpp" locate type M.S at "defs/defs-2.fpp" locate type M.SM.A at "defs/defs-2.fpp" @@ -45,13 +48,17 @@ locate type M.SM.E at "defs/defs-2.fpp" locate type M.SM.S at "defs/defs-2.fpp" locate type M.SM.State at "defs/defs-2.fpp" locate type M.SM.T at "defs/defs-2.fpp" +locate type M.SM.V at "defs/defs-2.fpp" locate type M.SM.X at "defs/defs-2.fpp" locate type M.T at "defs/defs-2.fpp" +locate type M.V at "defs/defs-2.fpp" locate type S at "defs/defs-1.fpp" locate type SM.A at "defs/defs-1.fpp" locate type SM.E at "defs/defs-1.fpp" locate type SM.S at "defs/defs-1.fpp" locate type SM.State at "defs/defs-1.fpp" locate type SM.T at "defs/defs-1.fpp" +locate type SM.V at "defs/defs-1.fpp" locate type SM.X at "defs/defs-1.fpp" locate type T at "defs/defs-1.fpp" +locate type V at "defs/defs-1.fpp" diff --git a/compiler/tools/fpp-locate-defs/test/defs/defs-1.fpp b/compiler/tools/fpp-locate-defs/test/defs/defs-1.fpp index d58128b22..819175e4c 100644 --- a/compiler/tools/fpp-locate-defs/test/defs/defs-1.fpp +++ b/compiler/tools/fpp-locate-defs/test/defs/defs-1.fpp @@ -1,5 +1,7 @@ array A = [3] U32 +vector V = [size 3] U32 + constant a = 0 dictionary constant a2 = 1 @@ -20,6 +22,7 @@ state machine SM { type T type X = T array A = [3] U32 + vector V = [size 3] U32 constant a = 0 enum E { X, Y, Z } struct S { x: U32 } @@ -34,6 +37,8 @@ passive component C { type Alias = T array A = [3] U32 dictionary array A2 = [3] U32 + vector V = [size 3] U32 + dictionary vector V2 = [size 3] U32 constant a = 0 enum E { X, Y, Z } struct S { x: U32 } diff --git a/compiler/tools/fpp-locate-defs/test/defs/defs-2.fpp b/compiler/tools/fpp-locate-defs/test/defs/defs-2.fpp index 2bd385541..b44fce662 100644 --- a/compiler/tools/fpp-locate-defs/test/defs/defs-2.fpp +++ b/compiler/tools/fpp-locate-defs/test/defs/defs-2.fpp @@ -2,6 +2,8 @@ module M { array A = [3] U32 + vector V = [size 3] U32 + constant a = 0 enum E { X, Y, Z } @@ -18,6 +20,7 @@ module M { type T type X = T array A = [3] U32 + vector V = [size 3] U32 constant a = 0 enum E { X, Y, Z } struct S { x: U32 } @@ -27,6 +30,7 @@ module M { type T type Alias = T array A = [3] U32 + vector V = [size 3] U32 constant a = 0 enum E { X, Y, Z } dictionary enum E2 { A, B, C } diff --git a/compiler/tools/fpp-locate-defs/test/defs_dir.ref.txt b/compiler/tools/fpp-locate-defs/test/defs_dir.ref.txt index 9c6b363c6..1665762ce 100644 --- a/compiler/tools/fpp-locate-defs/test/defs_dir.ref.txt +++ b/compiler/tools/fpp-locate-defs/test/defs_dir.ref.txt @@ -9,6 +9,7 @@ locate constant a at "defs-1.fpp" locate dictionary constant a2 at "defs-1.fpp" locate dictionary type Alias2 at "defs-1.fpp" locate dictionary type C.A2 at "defs-1.fpp" +locate dictionary type C.V2 at "defs-1.fpp" locate dictionary type M.C.E2 at "defs-2.fpp" locate dictionary type M.C.S2 at "defs-2.fpp" locate instance M.T at "defs-2.fpp" @@ -30,6 +31,7 @@ locate type C.Alias at "defs-1.fpp" locate type C.E at "defs-1.fpp" locate type C.S at "defs-1.fpp" locate type C.T at "defs-1.fpp" +locate type C.V at "defs-1.fpp" locate type E at "defs-1.fpp" locate type M.A at "defs-2.fpp" locate type M.Alias at "defs-2.fpp" @@ -38,6 +40,7 @@ locate type M.C.Alias at "defs-2.fpp" locate type M.C.E at "defs-2.fpp" locate type M.C.S at "defs-2.fpp" locate type M.C.T at "defs-2.fpp" +locate type M.C.V at "defs-2.fpp" locate type M.E at "defs-2.fpp" locate type M.S at "defs-2.fpp" locate type M.SM.A at "defs-2.fpp" @@ -45,13 +48,17 @@ locate type M.SM.E at "defs-2.fpp" locate type M.SM.S at "defs-2.fpp" locate type M.SM.State at "defs-2.fpp" locate type M.SM.T at "defs-2.fpp" +locate type M.SM.V at "defs-2.fpp" locate type M.SM.X at "defs-2.fpp" locate type M.T at "defs-2.fpp" +locate type M.V at "defs-2.fpp" locate type S at "defs-1.fpp" locate type SM.A at "defs-1.fpp" locate type SM.E at "defs-1.fpp" locate type SM.S at "defs-1.fpp" locate type SM.State at "defs-1.fpp" locate type SM.T at "defs-1.fpp" +locate type SM.V at "defs-1.fpp" locate type SM.X at "defs-1.fpp" locate type T at "defs-1.fpp" +locate type V at "defs-1.fpp" diff --git a/compiler/tools/fpp-locate-uses/test/defs.fpp b/compiler/tools/fpp-locate-uses/test/defs.fpp index 59aff1a92..cbe3d21c8 100644 --- a/compiler/tools/fpp-locate-uses/test/defs.fpp +++ b/compiler/tools/fpp-locate-uses/test/defs.fpp @@ -20,6 +20,7 @@ module Fw { } dictionary array A = [3] U32 +vector V = [size 3] U32 constant a = 0 enum E { X, Y } enum Phases { setup, teardown } @@ -51,6 +52,7 @@ port P active component C1 { async input port pIn: P array A = [3] U32 + vector V = [size 3] U32 constant a = 0 enum E { X, Y } dictionary struct S { x: U32 } diff --git a/compiler/tools/fpp-locate-uses/test/stdin.ref.txt b/compiler/tools/fpp-locate-uses/test/stdin.ref.txt index da68c77fa..3563cad8f 100644 --- a/compiler/tools/fpp-locate-uses/test/stdin.ref.txt +++ b/compiler/tools/fpp-locate-uses/test/stdin.ref.txt @@ -48,6 +48,7 @@ locate type ActionType at "defs.fpp" locate type C1.A at "defs.fpp" locate type C1.E at "defs.fpp" locate type C1.T at "defs.fpp" +locate type C1.V at "defs.fpp" locate type E at "defs.fpp" locate type FwSizeStoreType at "defs.fpp" locate type GuardType at "defs.fpp" @@ -64,3 +65,4 @@ locate type SM.X at "defs.fpp" locate type SignalType at "defs.fpp" locate type SizeOfType at "defs.fpp" locate type T at "defs.fpp" +locate type V at "defs.fpp" diff --git a/compiler/tools/fpp-locate-uses/test/uses.ref.txt b/compiler/tools/fpp-locate-uses/test/uses.ref.txt index 063436b04..10819ed53 100644 --- a/compiler/tools/fpp-locate-uses/test/uses.ref.txt +++ b/compiler/tools/fpp-locate-uses/test/uses.ref.txt @@ -49,6 +49,7 @@ locate type ActionType at "defs.fpp" locate type C1.A at "defs.fpp" locate type C1.E at "defs.fpp" locate type C1.T at "defs.fpp" +locate type C1.V at "defs.fpp" locate type E at "defs.fpp" locate type FwSizeStoreType at "defs.fpp" locate type GuardType at "defs.fpp" @@ -66,3 +67,4 @@ locate type SM1.State at "uses/uses.fpp" locate type SignalType at "defs.fpp" locate type SizeOfType at "defs.fpp" locate type T at "defs.fpp" +locate type V at "defs.fpp" diff --git a/compiler/tools/fpp-locate-uses/test/uses/uses.fpp b/compiler/tools/fpp-locate-uses/test/uses/uses.fpp index d7a37c6ec..650c8d95b 100644 --- a/compiler/tools/fpp-locate-uses/test/uses/uses.fpp +++ b/compiler/tools/fpp-locate-uses/test/uses/uses.fpp @@ -1,4 +1,5 @@ array A_use = [3] A +array V_use = [3] V constant a_use = a array T_use = [3] T array S_use = [3] S @@ -20,6 +21,7 @@ module M { passive component C2 { sync input port P_use: P array C1_A_use = [3] C1.A + array C1_V_use = [3] C1.V constant C1_a_use = C1.a array C1_S_use = [3] C1.S array C1_T_use = [3] C1.T diff --git a/compiler/tools/fpp-locate-uses/test/uses_dir.ref.txt b/compiler/tools/fpp-locate-uses/test/uses_dir.ref.txt index 69408ef07..3e7e04653 100644 --- a/compiler/tools/fpp-locate-uses/test/uses_dir.ref.txt +++ b/compiler/tools/fpp-locate-uses/test/uses_dir.ref.txt @@ -49,6 +49,7 @@ locate type ActionType at "../defs.fpp" locate type C1.A at "../defs.fpp" locate type C1.E at "../defs.fpp" locate type C1.T at "../defs.fpp" +locate type C1.V at "../defs.fpp" locate type E at "../defs.fpp" locate type FwSizeStoreType at "../defs.fpp" locate type GuardType at "../defs.fpp" @@ -66,3 +67,4 @@ locate type SM1.State at "uses.fpp" locate type SignalType at "../defs.fpp" locate type SizeOfType at "../defs.fpp" locate type T at "../defs.fpp" +locate type V at "../defs.fpp" diff --git a/compiler/tools/fpp/src/main/scala/fpp-locate-uses.scala b/compiler/tools/fpp/src/main/scala/fpp-locate-uses.scala index 20a3510c8..089802fc2 100644 --- a/compiler/tools/fpp/src/main/scala/fpp-locate-uses.scala +++ b/compiler/tools/fpp/src/main/scala/fpp-locate-uses.scala @@ -74,6 +74,7 @@ object FPPLocateUses { case _: Symbol.Struct => Ast.SpecLoc.Type case _: Symbol.System => throw InternalError("use should not be system symbol") case _: Symbol.Topology => Ast.SpecLoc.Instance + case _: Symbol.Vector => Ast.SpecLoc.Type } val isDictionaryDef = s match { case Symbol.Array(aNode) => aNode._2.data.isDictionaryDef @@ -81,6 +82,7 @@ object FPPLocateUses { case Symbol.Struct(aNode) => aNode._2.data.isDictionaryDef case Symbol.Enum(aNode) => aNode._2.data.isDictionaryDef case Symbol.Constant(aNode) => aNode._2.data.isDictionaryDef + case Symbol.Vector(aNode) => aNode._2.data.isDictionaryDef case _ => false } val specLocNode = AstNode.create(Ast.SpecLoc(kind, qualIdentNode, fileNode, isDictionaryDef))