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 alias syntax & semantics #591

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
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
2,152 changes: 1,082 additions & 1,070 deletions compiler/lib/src/main/resources/META-INF/native-image/reflect-config.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ 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
typeNameNode(a, data.typeName)
}

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 @@ -42,6 +42,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
58 changes: 56 additions & 2 deletions compiler/lib/src/main/scala/analysis/Semantics/Type.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,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 +39,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 +184,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 = aliasType.getDefaultValue
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 @@ -347,6 +367,7 @@ object Type {
/** Check for type identity */
def areIdentical(t1: Type, t2: Type): Boolean = {
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 +394,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 @@ -415,7 +441,6 @@ object Type {
array ||
struct
}

/** Compute the common type for a pair of types */
def commonType(t1: Type, t2: Type): Option[Type] = {
val pair = (t1, t2)
Expand All @@ -431,6 +456,34 @@ object Type {
case true => Some(t1)
case false => None
}
def alias() = {
def lca(a: Type, b: Type): Option[Type] = {
def getAncestors(t: Type, ancs: List[Type] = List()): List[Type] = {
t match {
case AliasType(_, parentType) =>
getAncestors(parentType, t :: ancs)
case _ =>
t :: ancs
}
}

// Reverse the ancestor list since `getAncestors` returns
// the ancestors with the oldest ancestor first.
val ancestorsOfA = getAncestors(a).reverse
val ancestorsOfB = getAncestors(b).reverse

// Traverse the ancestry of 'b' until we find a common ancestor with 'a'
ancestorsOfB.find(bi => ancestorsOfA.find(ai => areIdentical(ai, bi)).isDefined)
}

// If either type is an alias, first their common
if (!t1.isCanonical || !t2.isCanonical)
lca(t1, t2) match {
case None => commonType(t1.getUnderlyingType, t2.getUnderlyingType)
case Some(c) => Some(c)
}
else None
}
def numeric() =
if (t1.isFloat && t2.isNumeric) Some(Float(Float.F64))
else if (t1.isNumeric && t2.isFloat) Some(Float(Float.F64))
Expand Down Expand Up @@ -524,6 +577,7 @@ object Type {
}
val rules: List[Rule] = List(
identical,
alias,
numeric,
string,
enumeration,
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
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 @@ -224,6 +230,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 @@ -288,6 +296,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 @@ -138,6 +140,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 @@ -176,6 +179,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
10 changes: 10 additions & 0 deletions compiler/lib/src/main/scala/codegen/AstWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ object AstWriter extends AstVisitor with LineUtils {

def transUnit(tu: Ast.TransUnit): Out = transUnit((), tu)

override def defAliasTypeAnnotatedNode(
in: Unit,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]): Out = {
val (_, node, _) = aNode
lines("def alias type") ++ (
ident(node.data.name) ++
typeNameNode(node.data.typeName)
).map(indentIn)
}

override def defAbsTypeAnnotatedNode(
in: In,
aNode: Ast.Annotated[AstNode[Ast.DefAbsType]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,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 @@ -496,7 +496,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
Loading