Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Type aliases #549

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ trait TypeExpressionAnalyzer
opt(typeNameNode)(a, node.data.typeName)
}

override def defAliasTypeAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefAliasType]]) = {
val (_, node1, _) = node
val data = node1.data
for {
a <- typeNameNode(a, data.typeName)
} yield a
}

override def defArrayAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefArray]]) = {
val (_, node1, _) = node
val data = node1.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package fpp.compiler.analysis

import fpp.compiler.ast._
import fpp.compiler.util._
import fpp.compiler.ast.Ast.Annotated
import fpp.compiler.ast.Ast.DefAliasType

/** Compute and check expression types, except for array sizes
* and default values */
Expand Down Expand Up @@ -42,6 +44,19 @@ object CheckExprTypes extends UseAnalyzer {
else Right(a)
}

// override def defAliasTypeAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]) = {
// val (_, node,_) = aNode
// if (!a.typeMap.contains(node.id)) {
// val data = node.data
// for (a <- super.defAliasTypeAnnotatedNode(a, aNode))
// yield {
// val t = a.typeMap(data.typeName.id)
// a.assignType(node -> t)
// }
// }
// else Right(a)
// }

override def defEnumAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefEnum]]) = {
val (_, node, _) = aNode
val data = node.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ object CheckTypeUses extends UseAnalyzer {
visitIfNeeded(visitor)(a, aNode)
}

override def defAliasTypeAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]) = {
def visitor(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]) = {
for (a <- super.defAliasTypeAnnotatedNode(a, aNode))
yield {
val (_, node, _) = aNode
val data = node.data
val aliasedType = a.typeMap(data.typeName.id)
val t = Type.AliasType(aNode, aliasedType)
a.assignType(node -> t)
}
}
visitIfNeeded(visitor)(a, aNode)
}

override def defArrayAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefArray]]) = {
def visitor(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefArray]]) =
for (a <- super.defArrayAnnotatedNode(a, aNode))
Expand Down Expand Up @@ -135,6 +149,7 @@ object CheckTypeUses extends UseAnalyzer {
for {
a <- symbol match {
case Symbol.AbsType(node) => defAbsTypeAnnotatedNode(a, node)
case Symbol.AliasType(node) => defAliasTypeAnnotatedNode(a, node)
case Symbol.Array(node) => defArrayAnnotatedNode(a, node)
case Symbol.Enum(node) => defEnumAnnotatedNode(a, node)
case Symbol.Struct(node) => defStructAnnotatedNode(a, node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ object EnterSymbols
yield updateMap(a, symbol).copy(nestedScope = nestedScope)
}

override def defAliasTypeAnnotatedNode(
a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
) = {
val (_, node, _) = aNode
val data = node.data
val name = data.name
val symbol = Symbol.AliasType(aNode)
val nestedScope = a.nestedScope
for (nestedScope <- nestedScope.put(NameGroup.Type)(name, symbol))
yield updateMap(a, symbol).copy(nestedScope = nestedScope)
}

override def defArrayAnnotatedNode(
a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefArray]]
Expand Down
4 changes: 4 additions & 0 deletions compiler/lib/src/main/scala/analysis/Semantics/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ object Symbol {
override def getNodeId = node._2.id
override def getUnqualifiedName = node._2.data.name
}
final case class AliasType(node: Ast.Annotated[AstNode[Ast.DefAliasType]]) extends Symbol {
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 getNodeId = node._2.id
override def getUnqualifiedName = node._2.data.name
Expand Down
37 changes: 34 additions & 3 deletions compiler/lib/src/main/scala/analysis/Semantics/Type.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fpp.compiler.analysis
import fpp.compiler.ast._
import fpp.compiler.util._
import java.lang
import scala.annotation.constructorOnly

/** An FPP Type */
sealed trait Type {
Expand All @@ -16,6 +17,8 @@ sealed trait Type {
/** Get the definition node identifier, if any */
def getDefNodeId: Option[AstNode.Id] = None

def getUnderlyingType: Type = this

/** Does this type have numeric members? */
def hasNumericMembers: Boolean = isNumeric

Expand All @@ -37,6 +40,9 @@ sealed trait Type {
/** Is this type a primitive type? */
def isPrimitive: Boolean = false

/** Is this type a canonical (non-aliased) type? */
def isCanonical: Boolean = true

/** Is this type promotable to a struct type? */
final def isPromotableToStruct = isPromotableToArray

Expand Down Expand Up @@ -179,6 +185,21 @@ object Type {
override def getDefNodeId = Some(node._2.id)
override def toString = node._2.data.name
}

/** An alias 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 {
override def getDefaultValue = Some(Value.AliasType(this))
override def getDefNodeId = Some(node._2.id)
override def toString = node._2.data.name
override def isCanonical = false
override def getUnderlyingType = aliasType.getUnderlyingType
}

/** A named array type */
case class Array(
Expand Down Expand Up @@ -345,8 +366,11 @@ object Type {
}

/** Check for type identity */
def areIdentical(t1: Type, t2: Type): Boolean = {
def areIdentical(t1Aliased: Type, t2Aliased: Type): Boolean = {
val t1 = t1Aliased.getUnderlyingType
val t2 = t2Aliased.getUnderlyingType
val pair = (t1, t2)

def numeric = pair match {
case (PrimitiveInt(kind1), PrimitiveInt(kind2)) => kind1 == kind2
case (Float(kind1), Float(kind2)) => kind1 == kind2
Expand All @@ -373,8 +397,13 @@ object Type {
}

/** Check for type convertibility */
def mayBeConverted(pair: (Type, Type)): Boolean = {
def mayBeConverted(aliasPair: (Type, Type)): Boolean = {
val pair = (aliasPair._1.getUnderlyingType, aliasPair._2.getUnderlyingType)
val t1 -> t2 = pair

assert(t1.isCanonical)
assert(t2.isCanonical)

def numeric = t1.isConvertibleToNumeric && t2.isNumeric
def string = pair match {
case (String(_) -> String(_)) => true
Expand Down Expand Up @@ -417,7 +446,9 @@ object Type {
}

/** Compute the common type for a pair of types */
def commonType(t1: Type, t2: Type): Option[Type] = {
def commonType(t1Alias: Type, t2Alias: Type): Option[Type] = {
val t1 = t1Alias.getUnderlyingType
val t2 = t2Alias.getUnderlyingType
val pair = (t1, t2)
type Rule = () => Option[Type]
def selectFirstMatchIn(rules: List[Rule]): Option[Type] = rules match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ trait TypeVisitor {

def absType(in: In, t: Type.AbsType): Out = default(in, t)

def aliasType(in: In, t: Type.AliasType): Out = default(in, t)

def anonArray(in: In, t: Type.AnonArray): Out = default(in, t)

def anonStruct(in: In, t: Type.AnonStruct): Out = default(in, t)
Expand Down Expand Up @@ -36,6 +38,7 @@ trait TypeVisitor {
final def matchType(in: In, t: Type): Out =
t match {
case t : Type.AbsType => absType(in, t)
case t : Type.AliasType => aliasType(in, t)
case t : Type.AnonArray => anonArray(in, t)
case t : Type.AnonStruct => anonStruct(in, t)
case t : Type.Array => array(in, t)
Expand Down
9 changes: 9 additions & 0 deletions compiler/lib/src/main/scala/analysis/Semantics/Value.scala
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,15 @@ object Value {

}

/** An alias type */
case class AliasType(t: Type.AliasType) extends Value {

override def getType = t

override def toString = s"$t (${t.getUnderlyingType})"

}

/** Array values */
case class Array(anonArray: AnonArray, t: Type.Array) extends Value {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ trait ValueVisitor {

def absType(in: In, v: Value.AbsType): Out = default(in, v)

def aliasType(in: In, v: Value.AliasType): Out = default(in, v)

def anonArray(in: In, v: Value.AnonArray): Out = default(in, v)

def anonStruct(in: In, v: Value.AnonStruct): Out = default(in, v)
Expand Down Expand Up @@ -42,6 +44,7 @@ trait ValueVisitor {
case v : Value.String => string(in, v)
case v : Value.AnonArray => anonArray(in, v)
case v : Value.AbsType => absType(in, v)
case v : Value.AliasType => aliasType(in, v)
case v : Value.Array => array(in, v)
case v : Value.EnumConstant => enumConstant(in, v)
case v : Value.AnonStruct => anonStruct(in, v)
Expand Down
1 change: 1 addition & 0 deletions compiler/lib/src/main/scala/analysis/UsedSymbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ object UsedSymbols extends UseAnalyzer {
def helper(s: Symbol): Set[Symbol] = {
val Right(a2) = s match {
case Symbol.AbsType(node) => defAbsTypeAnnotatedNode(a1, node)
case Symbol.AliasType(node) => defAliasTypeAnnotatedNode(a1, node)
case Symbol.Array(node) => defArrayAnnotatedNode(a1, node)
case Symbol.Component(node) => defComponentAnnotatedNode(a1, node)
case Symbol.ComponentInstance(node) => defComponentInstanceAnnotatedNode(a1, node)
Expand Down
8 changes: 8 additions & 0 deletions compiler/lib/src/main/scala/ast/Ast.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ object Ast {
object ComponentMember {
sealed trait Node
final case class DefAbsType(node: AstNode[Ast.DefAbsType]) extends Node
final case class DefAliasType(node: AstNode[Ast.DefAliasType]) extends Node
final case class DefArray(node: AstNode[Ast.DefArray]) extends Node
final case class DefConstant(node: AstNode[Ast.DefConstant]) extends Node
final case class DefEnum(node: AstNode[Ast.DefEnum]) extends Node
Expand All @@ -73,6 +74,12 @@ object Ast {
/** Abstract type definition */
final case class DefAbsType(name: Ident)

/* Aliased type definition */
final case class DefAliasType(
name: Ident,
typeName: AstNode[TypeName]
)

/* Array definition */
final case class DefArray(
name: Ident,
Expand Down Expand Up @@ -131,6 +138,7 @@ object Ast {
object ModuleMember {
sealed trait Node
final case class DefAbsType(node: AstNode[Ast.DefAbsType]) extends Node
final case class DefAliasType(node: AstNode[Ast.DefAliasType]) extends Node
final case class DefArray(node: AstNode[Ast.DefArray]) extends Node
final case class DefComponent(node: AstNode[Ast.DefComponent]) extends Node
final case class DefComponentInstance(node: AstNode[Ast.DefComponentInstance]) extends Node
Expand Down
10 changes: 10 additions & 0 deletions compiler/lib/src/main/scala/ast/AstTransformer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ trait AstTransformer {
): ResultAnnotatedNode[Ast.DefAbsType] =
Right(default(in), node)

def defAliasTypeAnnotatedNode(
in: In,
node: Ast.Annotated[AstNode[Ast.DefAliasType]]
): ResultAnnotatedNode[Ast.DefAliasType] =
Right(default(in), node)

def defArrayAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefArray]]): ResultAnnotatedNode[Ast.DefArray] =
Right(default(in), node)

Expand Down Expand Up @@ -214,6 +220,8 @@ trait AstTransformer {
node match {
case Ast.ComponentMember.DefAbsType(node1) =>
transform(defAbsTypeAnnotatedNode(in, (pre, node1, post)), Ast.ComponentMember.DefAbsType(_))
case Ast.ComponentMember.DefAliasType(node1) =>
transform(defAliasTypeAnnotatedNode(in, (pre, node1, post)), Ast.ComponentMember.DefAliasType(_))
case Ast.ComponentMember.DefArray(node1) =>
transform(defArrayAnnotatedNode(in, (pre, node1, post)), Ast.ComponentMember.DefArray(_))
case Ast.ComponentMember.DefConstant(node1) =>
Expand Down Expand Up @@ -278,6 +286,8 @@ trait AstTransformer {
node match {
case Ast.ModuleMember.DefAbsType(node1) =>
transform(defAbsTypeAnnotatedNode(in, (pre, node1, post)), Ast.ModuleMember.DefAbsType(_))
case Ast.ModuleMember.DefAliasType(node1) =>
transform(defAliasTypeAnnotatedNode(in, (pre, node1, post)), Ast.ModuleMember.DefAliasType(_))
case Ast.ModuleMember.DefArray(node1) =>
transform(defArrayAnnotatedNode(in, (pre, node1, post)), Ast.ModuleMember.DefArray(_))
case Ast.ModuleMember.DefComponent(node1) =>
Expand Down
4 changes: 4 additions & 0 deletions compiler/lib/src/main/scala/ast/AstVisitor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ 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 defArrayAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefArray]]): Out = default(in)
Expand Down Expand Up @@ -134,6 +136,7 @@ trait AstVisitor {
val (pre, node, post) = member.node
node match {
case Ast.ComponentMember.DefAbsType(node1) => defAbsTypeAnnotatedNode(in, (pre, node1, post))
case Ast.ComponentMember.DefAliasType(node1) => defAliasTypeAnnotatedNode(in, (pre, node1, post))
case Ast.ComponentMember.DefArray(node1) => defArrayAnnotatedNode(in, (pre, node1, post))
case Ast.ComponentMember.DefConstant(node1) => defConstantAnnotatedNode(in, (pre, node1, post))
case Ast.ComponentMember.DefEnum(node1) => defEnumAnnotatedNode(in, (pre, node1, post))
Expand Down Expand Up @@ -172,6 +175,7 @@ trait AstVisitor {
val (pre, node, post) = member.node
node match {
case Ast.ModuleMember.DefAbsType(node1) => defAbsTypeAnnotatedNode(in, (pre, node1, post))
case Ast.ModuleMember.DefAliasType(node1) => defAliasTypeAnnotatedNode(in, (pre, node1, post))
case Ast.ModuleMember.DefArray(node1) => defArrayAnnotatedNode(in, (pre, node1, post))
case Ast.ModuleMember.DefComponent(node1) => defComponentAnnotatedNode(in, (pre, node1, post))
case Ast.ModuleMember.DefComponentInstance(node1) => defComponentInstanceAnnotatedNode(in, (pre, node1, post))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ case class ComponentDataProducts (
private def arrayRecordSerializeFn(name: String, t: Type) = {
// Get the type name and parameter type
val typeName = TypeCppWriter.getName(s, t)
val paramType = t match {
val paramType = t.getUnderlyingType match {
case Type.String(_) => "const Fw::StringBase**"
case _ => s"const ${typeName}*"
}
Expand All @@ -493,7 +493,7 @@ case class ComponentDataProducts (
| size * $eltSize;"""
}).stripMargin
// Generate the code for serializing the elements
val serializeElts = (t match {
val serializeElts = (t.getUnderlyingType match {
// Optimize the U8 case
case Type.U8 =>
"""| status = this->m_dataBuffer.serialize(array, size, Fw::Serialization::OMIT_LENGTH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ object ComputeCppFiles {
/** Gets the C++ file name for generated arrays */
def getArray(baseName: String) = s"${baseName}ArrayAc"

/** Gets the C++ file name for generated type aliases (typedefs) */
def getAliasType(baseName: String) = s"${baseName}TypeAc"

/** Gets the C++ file name for generated components */
def getComponent(baseName: String) = s"${baseName}ComponentAc"

Expand Down
Loading
Loading