Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a4209a7
Implement type alias syntax
Kronos3 Feb 1, 2025
23489ac
Type alias codegen
Kronos3 Feb 3, 2025
bc7a7f7
Fix test bugs
Kronos3 Feb 3, 2025
5bcdb44
AliasTypes do not have values associated with them, they use the unde…
Kronos3 Feb 4, 2025
4d73006
Update fpp tests to remove alias values
Kronos3 Feb 4, 2025
a5ea983
Merge branch 'main' into tumbar-type-alias-syntax
bocchino Feb 10, 2025
a502906
Update fpp-to-cpp test scripts
bocchino Feb 10, 2025
332ce06
Regenerate native build trace
bocchino Feb 10, 2025
8e63c91
Pull out type alias codegen and put back builtin types
Kronos3 Feb 10, 2025
2dfc8e9
Clean up some imports, fix a ref
Kronos3 Feb 10, 2025
5301865
Clean up checkIdentical and some todos, fix include checking for type…
Kronos3 Feb 12, 2025
f43a5d3
Merge branch 'main' into tumbar-type-alias-syntax
bocchino Feb 13, 2025
8117b8f
Implement lca for AliasType commonType
Kronos3 Feb 13, 2025
91ed69d
Merge remote-tracking branch 'origin/tumbar-type-alias-syntax' into t…
Kronos3 Feb 13, 2025
6f742f1
Clean up the include directive computation for aliastypes
Kronos3 Feb 13, 2025
4b789e7
Fix up common type computation when no matching ancestors in type ali…
Kronos3 Feb 13, 2025
0bb6071
Merge remote-tracking branch 'origin/main' into tumbar-type-alias-syntax
Kronos3 Feb 13, 2025
e9b91ac
Clean up some typos
Kronos3 Feb 13, 2025
1398c4f
Revise type checking rules
bocchino Feb 18, 2025
15a1bd5
Revise spec
bocchino Feb 18, 2025
b2dbc03
Refactor Type.scala
bocchino Feb 19, 2025
895204d
Merge branch 'main' into tumbar-type-alias-syntax
bocchino Feb 19, 2025
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
60 changes: 58 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,36 @@ 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)
}

// Apply this rule if either of t1 and t2 is an alias type
if (!t1.isCanonical || !t2.isCanonical)
lca(t1, t2) match {
// If there is a least common ancestor, then use it
case Some(c) => Some(c)
// Otherwise use the common type of the undelrying types
case None => commonType(t1.getUnderlyingType, t2.getUnderlyingType)
}
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 +579,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