From 6f09d40309aa83be45a218f35d6aad0c0f303143 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 16:05:58 -0700
Subject: [PATCH 01/51] Revise spec
---
docs/fpp-spec.html | 81 +++++++++++++++----
docs/fpp-users-guide.html | 2 +-
docs/spec/Expansion-of-Templates.adoc | 45 +++++++----
.../Template-Expansion-Specifiers.adoc | 14 +++-
4 files changed, 109 insertions(+), 33 deletions(-)
diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html
index 56a2dd78e..73899fa0e 100644
--- a/docs/fpp-spec.html
+++ b/docs/fpp-spec.html
@@ -1003,7 +1003,12 @@ The F Prime Prime (FPP) Language Specification, Unreleased, after v3.4.0
18. Expansion of Templates
19. Types
@@ -9253,7 +9258,7 @@ 7.18.3. Examples
7.19. Template Expansion Specifiers
A template expansion specifier names a
-template
+module template definition
and specifies arguments for the parameters of the template.
During template expansion, it generates the definitions specified
by the template and the arguments.
@@ -9265,6 +9270,9 @@
7.19.1. Syntax
qual-ident
[
( template-arg-list )
+
]
+
[
+
{ module-member-sequence }
]
@@ -9290,6 +9298,17 @@
7.19.1. Syntax
+
+
+
The optional module member list represents the result of
+expanding the template.
+If a template expansion specifier has a module member
+list, then is called an expanded template.
+Otherwise it is called an unexpanded template.
+
7.19.2. Semantics
@@ -12172,19 +12191,33 @@
18. Expansion of Templates
Expansion of templates performs partial analysis
and syntactic expansion.
-It produces a new model in which each
-template
-expansion specifier S is transformed into an
-expanded template \$E = S { X }\$, where X
-is a copy of the syntax provided
+It produces a new model according to the following rules:
+
+
+
+-
+
For each unexpanded
+template
+expansion specifier S in the source model,
+transform S into an
+expanded template expansion specifier \$E = S { X }\$, where X
+is a copy of the module member list provided
by the template definition to which S refers.
-The expanded template E is not expressible in the syntax
-of the source language, but it is expressible in the internal
-representation of the model.
The syntax X behaves as if it were literally included in
the model at the point of E, except that there are
-special rules for resolving
+special rules for
resolving names that appear inside E.
+
+-
+
For each expanded template expansion specifier \$E = S { X
+}\$ in the source model, leave E unchanged.
+
+
+
+
+
Note in particular that applying template expansion twice
+(or, more generally, any number of times greater than one)
+is equivalent to applying template expansion once.
18.1. Algorithm
@@ -12201,8 +12234,8 @@
18.1. Algorithm
match all template expansion specifiers with the template definitions to which they refer.
-For each template expansion specifier S in M,
-do the following:
+For each unexpanded template expansion specifier S in M, do the
+following:
-
@@ -12221,7 +12254,9 @@
18.1. Algorithm
-
18.2. Example
+
18.2. Examples
+
+
18.2.1. Example 1
@@ -12265,13 +12300,25 @@
18.2. Example
module N {
- # The expanded template is expand M.T(constant 1) { constant c = a + b }
- expand M.T(constant 1)
+ expand M.T(constant 1) {
+
+ constant c = a + b
+
+ }
}
+
+
18.2.2. Example 2
+
+
Let model M be the same as model M' from the previous section.
+Then the template expansion specifier is expanded, so template
+expansion leaves the model unchanged (\$M' = M\$).
+
+
+
@@ -14526,7 +14573,7 @@
diff --git a/docs/fpp-users-guide.html b/docs/fpp-users-guide.html
index 17a587b60..f8c184f24 100644
--- a/docs/fpp-users-guide.html
+++ b/docs/fpp-users-guide.html
@@ -18571,7 +18571,7 @@ 19.4. S
diff --git a/docs/spec/Expansion-of-Templates.adoc b/docs/spec/Expansion-of-Templates.adoc
index e5400b340..9450b7ef4 100644
--- a/docs/spec/Expansion-of-Templates.adoc
+++ b/docs/spec/Expansion-of-Templates.adoc
@@ -2,21 +2,28 @@
Expansion of templates performs partial analysis
and syntactic expansion.
-It produces a new model in which each
-<> _S_ is transformed into an
-*expanded template* stem:[E = S { X }], where _X_
-is a copy of the syntax provided
+It produces a new model according to the following rules:
+
+. For each <> _S_ in the source model,
+transform _S_ into an
+expanded template expansion specifier stem:[E = S { X }], where _X_
+is a copy of the module member list provided
by the template definition to which _S_ refers.
-The expanded template _E_ is not expressible in the syntax
-of the source language, but it is expressible in the internal
-representation of the model.
The syntax _X_ behaves as if it were literally included in
the model at the point of _E_, except that there are
-special rules for resolving
+special rules for
<> that appear inside _E_.
+. For each expanded template expansion specifier stem:[E = S { X
+}] in the source model, leave _E_ unchanged.
+
+Note in particular that applying template expansion twice
+(or, more generally, any number of times greater than one)
+is equivalent to applying template expansion once.
+
=== Algorithm
Let _M_ be the model initially presented to the analyzer,
@@ -27,8 +34,8 @@ Construct the output model _M'_ as follows:
<> and to
match all template expansion specifiers with the template definitions to which they refer.
-. For each template expansion specifier _S_ in _M_,
- do the following:
+. For each unexpanded template expansion specifier _S_ in _M_, do the
+ following:
.. Let _T_ be the template definition referred to in _S_.
@@ -36,7 +43,9 @@ Construct the output model _M'_ as follows:
.. Replace _S_ with stem:[S { X }].
-=== Example
+=== Examples
+
+==== Example 1
*Model _M_:*
@@ -79,9 +88,17 @@ module M {
module N {
- # The expanded template is expand M.T(constant 1) { constant c = a + b }
- expand M.T(constant 1)
+ expand M.T(constant 1) {
+
+ constant c = a + b
+
+ }
}
----
+==== Example 2
+
+Let model _M_ be the same as model _M'_ from the previous section.
+Then the template expansion specifier is expanded, so template
+expansion leaves the model unchanged (stem:[M' = M]).
diff --git a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
index 30f6ac3dc..49b27b09c 100644
--- a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
+++ b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
@@ -1,7 +1,7 @@
=== Template Expansion Specifiers
A *template expansion specifier* names a
-<>
+<>
and specifies arguments for the parameters of the template.
During <>, it generates the definitions specified
by the template and the arguments.
@@ -13,6 +13,9 @@ by the template and the arguments.
_[_
`(` _template-arg-list_ `)`
_]_
+_[_
+`{` _module-member-sequence_ `}`
+_]_
_template-arg-list_ is an
<> in
@@ -28,6 +31,15 @@ Each template argument is one of the following:
. A *type template argument* `type` <>
+_module-member-sequence_ is the same as for a
+<>.
+
+The optional module member list represents the result of
+<>.
+If a template expansion specifier has a module member
+list, then is called an *expanded template*.
+Otherwise it is called an *unexpanded template*.
+
==== Semantics
. The qualified identifier must
From 8ab7f5e9908bf7b18030b8e0b6b08350e5359e9c Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 16:23:25 -0700
Subject: [PATCH 02/51] Revise spec; revise syntax
---
compiler/lib/src/main/scala/syntax/Parser.scala | 6 ++++--
compiler/lib/src/test/scala/syntax/Parser.scala | 8 ++++++++
docs/fpp-spec.html | 14 +++++++-------
docs/spec/Expansion-of-Templates.adoc | 10 +++++-----
.../Specifiers/Template-Expansion-Specifiers.adoc | 2 +-
5 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/compiler/lib/src/main/scala/syntax/Parser.scala b/compiler/lib/src/main/scala/syntax/Parser.scala
index 0a4daadb3..c88e5bf1b 100644
--- a/compiler/lib/src/main/scala/syntax/Parser.scala
+++ b/compiler/lib/src/main/scala/syntax/Parser.scala
@@ -1096,8 +1096,10 @@ object Parser extends Parsers {
val templateArgList = argList(templateArg)
def specTemplateExpand: Parser[Ast.SpecTemplateExpand] = {
- (expand ~>! node(qualIdent)) ~! templateArgList ^^ {
- case id ~ args => Ast.SpecTemplateExpand(id, args, None)
+ (expand ~>! node(qualIdent)) ~! templateArgList ~! opt(
+ module ~>! lbrace ~>! moduleMembers <~! rbrace
+ ) ^^ {
+ case id ~ args ~ membersOpt => Ast.SpecTemplateExpand(id, args, membersOpt)
}
}
diff --git a/compiler/lib/src/test/scala/syntax/Parser.scala b/compiler/lib/src/test/scala/syntax/Parser.scala
index 534ef5b51..7e0829a6e 100644
--- a/compiler/lib/src/test/scala/syntax/Parser.scala
+++ b/compiler/lib/src/test/scala/syntax/Parser.scala
@@ -542,13 +542,21 @@ class ParserSpec extends AnyWordSpec {
Parser.specTemplateExpand,
List(
"expand T",
+ "expand T module { constant a = 0 }",
"expand M.T()",
+ "expand M.T() module { constant a = 0 }",
"expand M.T(constant 1)",
+ "expand M.T(constant 1) module { constant a = 0 }",
"expand M.T(constant 1, constant 2)",
+ "expand M.T(constant 1, constant 2) module { constant a = 0 }",
"expand M.T(constant 1, constant 2, instance mod.$instance)",
+ "expand M.T(constant 1, constant 2, instance mod.$instance) module { constant a = 0 }",
"expand M.T(constant 1, constant 2, instance .mod.$instance, type Type.Name)",
+ "expand M.T(constant 1, constant 2, instance .mod.$instance, type Type.Name) module { constant a = 0 }",
"expand M.T(constant 1, instance .inst1, type U32)",
+ "expand M.T(constant 1, instance .inst1, type U32) module { constant a = 0 }",
"expand M.T(constant 1, constant 2, constant {member=1}, constant [1, 2])",
+ "expand M.T(constant 1, constant 2, constant {member=1}, constant [1, 2]) module { constant a = 0 }",
)
)
}
diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html
index 73899fa0e..41fe5c33a 100644
--- a/docs/fpp-spec.html
+++ b/docs/fpp-spec.html
@@ -9272,7 +9272,7 @@ 7.19.1. Syntax
( template-arg-list )
]
[
-{ module-member-sequence }
+module { module-member-sequence }
]
@@ -12200,7 +12200,7 @@
18. Expansion of Templates
template
expansion specifier
S in the source model,
transform
S into an
-expanded template expansion specifier \$E = S { X }\$, where
X
+expanded template expansion specifier
E =
S module { X }, where
X
is a copy of the module member list provided
by the template definition to which
S refers.
The syntax
X behaves as if it were literally included in
@@ -12209,8 +12209,8 @@
18. Expansion of Templates
resolving names that appear inside
E.
-For each expanded template expansion specifier \$E = S { X
-}\$ in the source model, leave E unchanged.
+For each expanded template expansion specifier E = S module { X }
+in the source model, leave E unchanged.
@@ -12245,7 +12245,7 @@ 18.1. Algorithm
Let X be a copy of the syntax specified in the body of T.
-Replace S with \$S { X }\$.
+Replace S with S module { X }.
@@ -12300,7 +12300,7 @@ 18.2.1. Example 1
module N {
- expand M.T(constant 1) {
+ expand M.T(constant 1) module {
constant c = a + b
@@ -14573,7 +14573,7 @@
diff --git a/docs/spec/Expansion-of-Templates.adoc b/docs/spec/Expansion-of-Templates.adoc
index 9450b7ef4..c583ba3a2 100644
--- a/docs/spec/Expansion-of-Templates.adoc
+++ b/docs/spec/Expansion-of-Templates.adoc
@@ -8,7 +8,7 @@ It produces a new model according to the following rules:
template
expansion specifier>> _S_ in the source model,
transform _S_ into an
-expanded template expansion specifier stem:[E = S { X }], where _X_
+expanded template expansion specifier _E_ = _S_ `module` `{` _X_ `}`, where _X_
is a copy of the module member list provided
by the template definition to which _S_ refers.
The syntax _X_ behaves as if it were literally included in
@@ -17,8 +17,8 @@ special rules for
<> that appear inside _E_.
-. For each expanded template expansion specifier stem:[E = S { X
-}] in the source model, leave _E_ unchanged.
+. For each expanded template expansion specifier _E_ = _S_ `module` `{` _X_ `}`
+in the source model, leave _E_ unchanged.
Note in particular that applying template expansion twice
(or, more generally, any number of times greater than one)
@@ -41,7 +41,7 @@ Construct the output model _M'_ as follows:
.. Let _X_ be a copy of the syntax specified in the body of _T_.
-.. Replace _S_ with stem:[S { X }].
+.. Replace _S_ with _S_ `module` `{` _X_ `}`.
=== Examples
@@ -88,7 +88,7 @@ module M {
module N {
- expand M.T(constant 1) {
+ expand M.T(constant 1) module {
constant c = a + b
diff --git a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
index 49b27b09c..664ad9a71 100644
--- a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
+++ b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
@@ -14,7 +14,7 @@ _[_
`(` _template-arg-list_ `)`
_]_
_[_
-`{` _module-member-sequence_ `}`
+`module` `{` _module-member-sequence_ `}`
_]_
_template-arg-list_ is an
From cfde476885dbf20e7c2491e1a5b3907110bf3158 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 16:35:22 -0700
Subject: [PATCH 03/51] Refactor AstWriter
---
.../lib/src/main/scala/codegen/AstWriter.scala | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/compiler/lib/src/main/scala/codegen/AstWriter.scala b/compiler/lib/src/main/scala/codegen/AstWriter.scala
index 8d5b30ec1..a03e01c92 100644
--- a/compiler/lib/src/main/scala/codegen/AstWriter.scala
+++ b/compiler/lib/src/main/scala/codegen/AstWriter.scala
@@ -186,23 +186,9 @@ object AstWriter extends AstVisitor with LineUtils {
).map(indentIn)
}
- override def specTemplateExpandAnnotatedNodeUnexpanded(
+ override def specTemplateExpandAnnotatedNode(
in: In,
aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
- ) = {
- val (_, node, _) = aNode
- val data = node.data
- lines("expand") ++
- List.concat(
- qualIdent(data.template.data),
- templateArgList(data.args)
- ).map(indentIn)
- }
-
- override def specTemplateExpandAnnotatedNodeExpanded(
- in: In,
- aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]],
- members: List[Ast.ModuleMember]
) = {
val (_, node, _) = aNode
val data = node.data
@@ -210,7 +196,7 @@ object AstWriter extends AstVisitor with LineUtils {
List.concat(
qualIdent(data.template.data),
templateArgList(data.args),
- members.flatMap(moduleMember)
+ data.members.getOrElse(Nil).flatMap(moduleMember)
).map(indentIn)
}
From 5bd18ab7bdb219811018b920b502a18586f3cc6e Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 17:11:24 -0700
Subject: [PATCH 04/51] Revise spec, syntax, and tests
---
.../lib/src/main/scala/syntax/Parser.scala | 2 +-
.../lib/src/test/scala/syntax/Parser.scala | 16 ++++----
compiler/tools/fpp-syntax/test/template.fpp | 18 +++++++--
.../tools/fpp-syntax/test/template.ref.txt | 38 ++++++++++---------
compiler/tools/fpp-syntax/test/update-ref | 2 +-
compiler/tools/fpp-to-fpp/test/run | 8 ++--
docs/fpp-spec.html | 12 +++---
docs/spec/Expansion-of-Templates.adoc | 8 ++--
.../Template-Expansion-Specifiers.adoc | 2 +-
9 files changed, 60 insertions(+), 46 deletions(-)
diff --git a/compiler/lib/src/main/scala/syntax/Parser.scala b/compiler/lib/src/main/scala/syntax/Parser.scala
index c88e5bf1b..3d721b582 100644
--- a/compiler/lib/src/main/scala/syntax/Parser.scala
+++ b/compiler/lib/src/main/scala/syntax/Parser.scala
@@ -1097,7 +1097,7 @@ object Parser extends Parsers {
def specTemplateExpand: Parser[Ast.SpecTemplateExpand] = {
(expand ~>! node(qualIdent)) ~! templateArgList ~! opt(
- module ~>! lbrace ~>! moduleMembers <~! rbrace
+ lbrace ~>! moduleMembers <~! rbrace
) ^^ {
case id ~ args ~ membersOpt => Ast.SpecTemplateExpand(id, args, membersOpt)
}
diff --git a/compiler/lib/src/test/scala/syntax/Parser.scala b/compiler/lib/src/test/scala/syntax/Parser.scala
index 7e0829a6e..b1c5d7657 100644
--- a/compiler/lib/src/test/scala/syntax/Parser.scala
+++ b/compiler/lib/src/test/scala/syntax/Parser.scala
@@ -542,21 +542,21 @@ class ParserSpec extends AnyWordSpec {
Parser.specTemplateExpand,
List(
"expand T",
- "expand T module { constant a = 0 }",
+ "expand T { constant a = 0 }",
"expand M.T()",
- "expand M.T() module { constant a = 0 }",
+ "expand M.T() { constant a = 0 }",
"expand M.T(constant 1)",
- "expand M.T(constant 1) module { constant a = 0 }",
+ "expand M.T(constant 1) { constant a = 0 }",
"expand M.T(constant 1, constant 2)",
- "expand M.T(constant 1, constant 2) module { constant a = 0 }",
+ "expand M.T(constant 1, constant 2) { constant a = 0 }",
"expand M.T(constant 1, constant 2, instance mod.$instance)",
- "expand M.T(constant 1, constant 2, instance mod.$instance) module { constant a = 0 }",
+ "expand M.T(constant 1, constant 2, instance mod.$instance) { constant a = 0 }",
"expand M.T(constant 1, constant 2, instance .mod.$instance, type Type.Name)",
- "expand M.T(constant 1, constant 2, instance .mod.$instance, type Type.Name) module { constant a = 0 }",
+ "expand M.T(constant 1, constant 2, instance .mod.$instance, type Type.Name) { constant a = 0 }",
"expand M.T(constant 1, instance .inst1, type U32)",
- "expand M.T(constant 1, instance .inst1, type U32) module { constant a = 0 }",
+ "expand M.T(constant 1, instance .inst1, type U32) { constant a = 0 }",
"expand M.T(constant 1, constant 2, constant {member=1}, constant [1, 2])",
- "expand M.T(constant 1, constant 2, constant {member=1}, constant [1, 2]) module { constant a = 0 }",
+ "expand M.T(constant 1, constant 2, constant {member=1}, constant [1, 2]) { constant a = 0 }",
)
)
}
diff --git a/compiler/tools/fpp-syntax/test/template.fpp b/compiler/tools/fpp-syntax/test/template.fpp
index 74a9c4b6e..21bf40104 100644
--- a/compiler/tools/fpp-syntax/test/template.fpp
+++ b/compiler/tools/fpp-syntax/test/template.fpp
@@ -15,6 +15,18 @@ module template Tmpl(
}
}
-@ Expansion specifier
-expand Tmpl(constant 10, type Type, instance .instance1)
-@< Expansion specifier
+module Unexpanded {
+
+ @ Unexpanded expansion specifier
+ expand Tmpl(constant 10, type Type, instance .instance1)
+ @< Unexpanded expansion specifier
+
+}
+
+#module Expanded {
+#
+# @ Expanded expansion specifier
+# expand Tmpl(constant 10, type Type, instance .instance1) { constant a = 0 }
+# @< Expanded expansion specifier
+#
+#}
diff --git a/compiler/tools/fpp-syntax/test/template.ref.txt b/compiler/tools/fpp-syntax/test/template.ref.txt
index faa0858fe..92987959c 100644
--- a/compiler/tools/fpp-syntax/test/template.ref.txt
+++ b/compiler/tools/fpp-syntax/test/template.ref.txt
@@ -22,21 +22,23 @@ def module template
ident Top
spec interface instance
qual ident inst
-@ Expansion specifier
-expand
- qual ident Tmpl
- constant template arg
- literal int 10
- type template arg
- type name qual ident Type
- instance template arg
- qual ident .instance1
- def array
- ident Arr
- size literal int 3
- type name qual ident TypeParam
- def topology
- ident Top
- spec interface instance
- qual ident inst
-@< Expansion specifier
+def module
+ ident Unexpanded
+ @ Unexpanded expansion specifier
+ expand
+ qual ident Tmpl
+ constant template arg
+ literal int 10
+ type template arg
+ type name qual ident Type
+ instance template arg
+ qual ident .instance1
+ def array
+ ident Arr
+ size literal int 3
+ type name qual ident TypeParam
+ def topology
+ ident Top
+ spec interface instance
+ qual ident inst
+ @< Unexpanded expansion specifier
diff --git a/compiler/tools/fpp-syntax/test/update-ref b/compiler/tools/fpp-syntax/test/update-ref
index 2f21c6bff..d036a8739 100755
--- a/compiler/tools/fpp-syntax/test/update-ref
+++ b/compiler/tools/fpp-syntax/test/update-ref
@@ -48,7 +48,7 @@ update -ia include-state-machine
update -ia include-subdir
update -ia include-topology
update -ia topology-ports
-update -ita template
+update -iea template
update -ia subdir/include-parent-dir
update -ia syntax syntax-include-ast
update "" numeric-shift
diff --git a/compiler/tools/fpp-to-fpp/test/run b/compiler/tools/fpp-to-fpp/test/run
index a86099346..b7486f291 100755
--- a/compiler/tools/fpp-to-fpp/test/run
+++ b/compiler/tools/fpp-to-fpp/test/run
@@ -69,16 +69,16 @@ dictionary_specifier()
$fpp_syntax dictionary_specifier.out.txt
}
-# Note: the expanded output uses the `expand ... { ... }` form, which is not
-# (yet) valid FPP surface syntax, so we do not round-trip it through fpp-syntax.
template_expand()
{
- run_test '-e' template_expand
+ run_test '-e' template_expand && \
+ $fpp_syntax template_expand.out.txt
}
template_include()
{
- run_test '-e' template_include
+ run_test '-e' template_include && \
+ $fpp_syntax template_include.out.txt
}
run_suite $tests
diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html
index 41fe5c33a..fcb52cc52 100644
--- a/docs/fpp-spec.html
+++ b/docs/fpp-spec.html
@@ -9272,7 +9272,7 @@ 7.19.1. Syntax
( template-arg-list )
]
[
-module { module-member-sequence }
+{ module-member-sequence }
]
@@ -12200,7 +12200,7 @@
18. Expansion of Templates
template
expansion specifier
S in the source model,
transform
S into an
-expanded template expansion specifier
E =
S module { X }, where
X
+expanded template expansion specifier
E =
S { X }, where
X
is a copy of the module member list provided
by the template definition to which
S refers.
The syntax
X behaves as if it were literally included in
@@ -12209,7 +12209,7 @@
18. Expansion of Templates
resolving names that appear inside
E.
-For each expanded template expansion specifier E = S module { X }
+
For each expanded template expansion specifier E = S { X }
in the source model, leave E unchanged.
@@ -12245,7 +12245,7 @@
18.1. Algorithm
Let X be a copy of the syntax specified in the body of T.
-Replace S with S module { X }.
+Replace S with S { X }.
@@ -12300,7 +12300,7 @@ 18.2.1. Example 1
module N {
- expand M.T(constant 1) module {
+ expand M.T(constant 1) {
constant c = a + b
@@ -14573,7 +14573,7 @@
diff --git a/docs/spec/Expansion-of-Templates.adoc b/docs/spec/Expansion-of-Templates.adoc
index c583ba3a2..e08553de1 100644
--- a/docs/spec/Expansion-of-Templates.adoc
+++ b/docs/spec/Expansion-of-Templates.adoc
@@ -8,7 +8,7 @@ It produces a new model according to the following rules:
template
expansion specifier>> _S_ in the source model,
transform _S_ into an
-expanded template expansion specifier _E_ = _S_ `module` `{` _X_ `}`, where _X_
+expanded template expansion specifier _E_ = _S_ `{` _X_ `}`, where _X_
is a copy of the module member list provided
by the template definition to which _S_ refers.
The syntax _X_ behaves as if it were literally included in
@@ -17,7 +17,7 @@ special rules for
<> that appear inside _E_.
-. For each expanded template expansion specifier _E_ = _S_ `module` `{` _X_ `}`
+. For each expanded template expansion specifier _E_ = _S_ `{` _X_ `}`
in the source model, leave _E_ unchanged.
Note in particular that applying template expansion twice
@@ -41,7 +41,7 @@ Construct the output model _M'_ as follows:
.. Let _X_ be a copy of the syntax specified in the body of _T_.
-.. Replace _S_ with _S_ `module` `{` _X_ `}`.
+.. Replace _S_ with _S_ `{` _X_ `}`.
=== Examples
@@ -88,7 +88,7 @@ module M {
module N {
- expand M.T(constant 1) module {
+ expand M.T(constant 1) {
constant c = a + b
diff --git a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
index 664ad9a71..49b27b09c 100644
--- a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
+++ b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
@@ -14,7 +14,7 @@ _[_
`(` _template-arg-list_ `)`
_]_
_[_
-`module` `{` _module-member-sequence_ `}`
+`{` _module-member-sequence_ `}`
_]_
_template-arg-list_ is an
From ebf0208dd6e124c551c90fdc4bd71792503bd80f Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 17:36:32 -0700
Subject: [PATCH 05/51] Revise analysis
Support syntactic analysis of expand specifiers with pre-expansions
Revise tests
---
.../src/main/scala/analysis/Analysis.scala | 2 +-
.../analysis/Analyzers/ModuleAnalyzer.scala | 21 +++++++++++--------
.../Semantics/TemplateExpansion.scala | 2 +-
compiler/tools/fpp-syntax/test/template.fpp | 14 ++++++-------
.../tools/fpp-syntax/test/template.ref.txt | 20 ++++++++++++++++++
5 files changed, 41 insertions(+), 18 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/Analysis.scala b/compiler/lib/src/main/scala/analysis/Analysis.scala
index 506775030..f9ed7d98c 100644
--- a/compiler/lib/src/main/scala/analysis/Analysis.scala
+++ b/compiler/lib/src/main/scala/analysis/Analysis.scala
@@ -90,7 +90,7 @@ case class Analysis(
impliedUseMap: Map[AstNode.Id, ImpliedUse.Uses] = Map(),
/** Node ID of the template expansion currently */
template: Option[AstNode.Id] = None,
- /** Maps template expansion AST nodes to their */
+ /** Maps template expansion AST nodes to their expansions */
templateExpansionMap: Map[AstNode.Id, TemplateExpansion] = Map(),
/** Tracks the current expansion we are analyzing inside of */
templateExpansion: Option[TemplateExpansion] = None,
diff --git a/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala b/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala
index 10604d50f..bca23d984 100644
--- a/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala
+++ b/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala
@@ -17,20 +17,23 @@ trait ModuleAnalyzer extends Analyzer {
yield a2.copy(scopeNameList = a.scopeNameList)
}
- override def specTemplateExpandAnnotatedNode(
+ override def specTemplateExpandAnnotatedNodeExpanded(
a: Analysis,
- aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
+ aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]],
+ members: List[Ast.ModuleMember]
) = {
val (_, node, _) = aNode
- // Check if this template has been expanded
- node.data.members match {
- case Some(members) => {
- // Mark the analysis with the proper expansion
- val a1 = a.copy(templateExpansion = Some(a.templateExpansionMap(node.id)))
+ a.templateExpansionMap.get(node.id) match {
+ case Some(expansion) =>
+ // This node has been expanded by analysis.
+ // Mark the analysis with the proper expansion.
+ val a1 = a.copy(templateExpansion = Some(expansion))
for { a2 <- visitList(a1, members, matchModuleMember) }
yield a2.copy(templateExpansion = a.templateExpansion)
- }
- case None => Right(a)
+ case None =>
+ // This node has not yet been expanded by analysis.
+ // The expansion is provided in an expand { ... } clause.
+ Right(a)
}
}
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/TemplateExpansion.scala b/compiler/lib/src/main/scala/analysis/Semantics/TemplateExpansion.scala
index a806ae441..dd90af846 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/TemplateExpansion.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/TemplateExpansion.scala
@@ -3,7 +3,7 @@ package fpp.compiler.analysis
import fpp.compiler.ast._
import fpp.compiler.util._
-/** An FPP template */
+/** An FPP template expansion */
case class TemplateExpansion(
/** The AST node defining the template */
defNode: Ast.Annotated[AstNode[Ast.DefModuleTemplate]],
diff --git a/compiler/tools/fpp-syntax/test/template.fpp b/compiler/tools/fpp-syntax/test/template.fpp
index 21bf40104..0748e77c0 100644
--- a/compiler/tools/fpp-syntax/test/template.fpp
+++ b/compiler/tools/fpp-syntax/test/template.fpp
@@ -23,10 +23,10 @@ module Unexpanded {
}
-#module Expanded {
-#
-# @ Expanded expansion specifier
-# expand Tmpl(constant 10, type Type, instance .instance1) { constant a = 0 }
-# @< Expanded expansion specifier
-#
-#}
+module Expanded {
+
+ @ Expanded expansion specifier
+ expand Tmpl(constant 10, type Type, instance .instance1) { constant a = 0 }
+ @< Expanded expansion specifier
+
+}
diff --git a/compiler/tools/fpp-syntax/test/template.ref.txt b/compiler/tools/fpp-syntax/test/template.ref.txt
index 92987959c..070cbb1d5 100644
--- a/compiler/tools/fpp-syntax/test/template.ref.txt
+++ b/compiler/tools/fpp-syntax/test/template.ref.txt
@@ -42,3 +42,23 @@ def module
spec interface instance
qual ident inst
@< Unexpanded expansion specifier
+def module
+ ident Expanded
+ @ Expanded expansion specifier
+ expand
+ qual ident Tmpl
+ constant template arg
+ literal int 10
+ type template arg
+ type name qual ident Type
+ instance template arg
+ qual ident .instance1
+ def array
+ ident Arr
+ size literal int 3
+ type name qual ident TypeParam
+ def topology
+ ident Top
+ spec interface instance
+ qual ident inst
+ @< Expanded expansion specifier
From 779f30f55c068567166231de27fb3e3739890c02 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 19:57:09 -0700
Subject: [PATCH 06/51] Revise ExpandTemplates
Refactor
Handle expansion provided in source
---
.../src/main/scala/analysis/Analysis.scala | 10 +-
.../scala/transform/ExpandTemplates.scala | 125 ++++++++++--------
.../tools/fpp-syntax/test/template.ref.txt | 11 +-
3 files changed, 78 insertions(+), 68 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/Analysis.scala b/compiler/lib/src/main/scala/analysis/Analysis.scala
index f9ed7d98c..d50c4c8cf 100644
--- a/compiler/lib/src/main/scala/analysis/Analysis.scala
+++ b/compiler/lib/src/main/scala/analysis/Analysis.scala
@@ -88,14 +88,14 @@ case class Analysis(
tlmPacketSet: Option[TlmPacketSet] = None,
/** The mapping from nodes to implied uses */
impliedUseMap: Map[AstNode.Id, ImpliedUse.Uses] = Map(),
- /** Node ID of the template expansion currently */
- template: Option[AstNode.Id] = None,
+ /** Node ID of the current template expansion */
+ templateExpansionId: Option[AstNode.Id] = None,
/** Maps template expansion AST nodes to their expansions */
templateExpansionMap: Map[AstNode.Id, TemplateExpansion] = Map(),
- /** Tracks the current expansion we are analyzing inside of */
+ /** The current template expansion */
templateExpansion: Option[TemplateExpansion] = None,
- /** Node ID of the template definition we are currently cloning inside of */
- templateDefinition: Option[AstNode.Id] = None,
+ /** Node ID of the current template definition */
+ templateDefinitionId: Option[AstNode.Id] = None,
/** The set of symbols defined with a dictionary specifier */
dictionarySymbolSet: Set[Symbol] = Set(),
/** The mapping from system symbols to systems */
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index e0244a078..06b34dbc9 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -50,7 +50,7 @@ object ExpandTemplates extends AstTransformer
a: Analysis,
node: AstNode[T]
) =
- a.template match {
+ a.templateExpansionId match {
case None => Right((), node)
case Some(expansionNode) => {
val out = AstNode.create(node.data)
@@ -80,7 +80,7 @@ object ExpandTemplates extends AstTransformer
a: In,
aNode: Ast.Annotated[AstNode[T]]
) = {
- a.template match {
+ a.templateExpansionId match {
// We are not currently in a template, leave the node alone
case None => Right((), aNode)
case Some(_) =>
@@ -95,7 +95,7 @@ object ExpandTemplates extends AstTransformer
node: AstNode[T],
data: T
) =
- a.template match {
+ a.templateExpansionId match {
case None => AstNode.create(data, node.id)
case Some(expansionNode) => {
val out = AstNode.create(data)
@@ -122,8 +122,8 @@ object ExpandTemplates extends AstTransformer
override def exprArrayNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprArray): ResultNode[Ast.Expr] =
for { result <- transformList(a, e.elts, matchExprNode) }
yield {
- val (a1, elts1) = result
- (a1, cloneNode(a, node, Ast.ExprArray(elts1)))
+ val (_, elts1) = result
+ ((), cloneNode(a, node, Ast.ExprArray(elts1)))
}
override def exprArraySubscriptNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprArraySubscript): ResultNode[Ast.Expr] =
@@ -151,15 +151,15 @@ object ExpandTemplates extends AstTransformer
override def exprDotNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprDot): ResultNode[Ast.Expr] =
for (result <- matchExprNode(a, e.e))
yield {
- val (a1, left) = result
- (a1, cloneNode(a, node, Ast.ExprDot(left, cloneNode(a, e.id, e.id.data))))
+ val (_, left) = result
+ ((), cloneNode(a, node, Ast.ExprDot(left, cloneNode(a, e.id, e.id.data))))
}
override def exprParenNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprParen): ResultNode[Ast.Expr] =
for (result <- matchExprNode(a, e.e))
yield {
- val (a1, value) = result
- (a1, cloneNode(a, node, Ast.ExprParen(value)))
+ val (_, value) = result
+ ((), cloneNode(a, node, Ast.ExprParen(value)))
}
def structMember(
@@ -168,8 +168,8 @@ object ExpandTemplates extends AstTransformer
) = {
for (result <- matchExprNode(a, node.data.value))
yield {
- val (a1, value) = result
- (a1, cloneNode(a, node, Ast.StructMember(
+ val (_, value) = result
+ ((), cloneNode(a, node, Ast.StructMember(
node.data.name,
value
)))
@@ -204,8 +204,8 @@ object ExpandTemplates extends AstTransformer
) =
for { result <- transformList(a, e.members, structMember) }
yield {
- val (a1, members1) = result
- (a1, cloneNode(a, node, Ast.ExprStruct(members1)))
+ val (_, members1) = result
+ ((), cloneNode(a, node, Ast.ExprStruct(members1)))
}
override def exprUnopNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprUnop) =
@@ -235,8 +235,8 @@ object ExpandTemplates extends AstTransformer
case Some(value) =>
for (result <- matchExprNode(a, value))
yield {
- val (a1, v1) = result
- (a1, Some(v1))
+ val (_, v1) = result
+ ((), Some(v1))
}
}
@@ -251,8 +251,8 @@ object ExpandTemplates extends AstTransformer
case Some(size) =>
for (result <- matchExprNode(a, size))
yield {
- val (a1, value) = result
- (a1, cloneNode(a, node, Ast.TypeNameString(Some(value))))
+ val (_, value) = result
+ ((), cloneNode(a, node, Ast.TypeNameString(Some(value))))
}
}
}
@@ -275,8 +275,8 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for (result <- matchTypeName(a, data.typeName))
yield {
- val (a1, ty) = result
- (a1, cloneAnnotatedNode(
+ val (_, ty) = result
+ ((), cloneAnnotatedNode(
a, aNode, data.copy(typeName = ty)
))
}
@@ -315,8 +315,8 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for (result <- transformList(a, data.members, matchComponentMember))
yield {
- val (a1, members1) = result
- (a1, cloneAnnotatedNode(a, aNode, data.copy(members = members1.flatten)))
+ val (_, members1) = result
+ ((), cloneAnnotatedNode(a, aNode, data.copy(members = members1.flatten)))
}
override def defComponentInstanceAnnotatedNode(
@@ -356,8 +356,8 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for (result <- transformList(a, data.members, matchInterfaceMember))
yield {
- val (a1, members1) = result
- (a1, cloneAnnotatedNode(a, aNode, data.copy(members=members1)))
+ val (_, members1) = result
+ ((), cloneAnnotatedNode(a, aNode, data.copy(members=members1)))
}
override def defConstantAnnotatedNode(
@@ -794,8 +794,8 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for (result <- matchExprNode(a, data.phase))
yield {
- val (a1, phase1) = result
- (a1, cloneAnnotatedNode(a, aNode, data.copy(phase=phase1)))
+ val (_, phase1) = result
+ ((), cloneAnnotatedNode(a, aNode, data.copy(phase=phase1)))
}
override def specInternalPortAnnotatedNode(
@@ -1067,17 +1067,17 @@ object ExpandTemplates extends AstTransformer
for {
// Validate no nested template
- _ <- a.templateDefinition match {
+ _ <- a.templateDefinitionId match {
case Some(parent) => Left(SemanticError.NestedTemplateDefinition(
Locations.get(aNode._2.id),
Locations.get(parent)
))
case None => Right(())
}
- a <- Right(a.copy(templateDefinition = Some(node.id)))
+ a <- Right(a.copy(templateDefinitionId = Some(node.id)))
params <- transformList(a, data.params, templateParam)
members <- transformList(a, data.members, matchModuleMember)
- a <- Right(a.copy(templateDefinition = None))
+ a <- Right(a.copy(templateDefinitionId = None))
}
yield {
val (_, params1) = params
@@ -1096,8 +1096,8 @@ object ExpandTemplates extends AstTransformer
val data = node.data
for { result <- transformList(a, data.members, matchModuleMember) }
yield {
- val (a1, members1) = result
- (a1, cloneAnnotatedNode(a, aNode, data.copy(members = members1.flatten)))
+ val (_, members1) = result
+ ((), cloneAnnotatedNode(a, aNode, data.copy(members = members1.flatten)))
}
}
@@ -1105,41 +1105,56 @@ object ExpandTemplates extends AstTransformer
a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
): ResultAnnotatedNode[Ast.SpecTemplateExpand] = {
- val (pre, node, post) = aNode
+ val (_, node, _) = aNode
val data = node.data
-
- (a.template, a.templateDefinition) match {
+ (a.templateExpansionId, a.templateDefinitionId) match {
case (None, None) =>
- // Not inside a template: expand it
- for {
- // Look up the template def
- tmpl <- a.getTemplateSymbol(data.template.id)
-
- // Clone the template body, recording the expansion node so that any
- // nested expansion specifier is rejected and so that cloned nodes
- // point back at the expansion site.
- // Record the template definition too for diagnostics.
- members <- transformList(
- a.copy(
- template = Some(node.id),
- templateDefinition = Some(tmpl.node._2.id)
- ),
- tmpl.node._2.data.members,
- matchModuleMember
- )
- } yield {
- // Paste the expanded template body into the expansion specifier
- ((), (pre, AstNode.create(data.copy(members = Some(members._2.flatten)), node.id), post))
+ // Not inside a template: expand if needed
+ data.members match {
+ // Members are already there; nothing to do
+ case Some(members) => Right((), aNode)
+ // Members are not there; expand
+ case None => expandTemplate(a, aNode)
}
- case (_, Some(templateDefinition)) =>
+ case (_, Some(templateDefinitionId)) =>
// The expansion specifier is nested inside a template body
Left(SemanticError.TemplateExpansionInTemplate(
Locations.get(node.id),
- Locations.get(templateDefinition)
+ Locations.get(templateDefinitionId)
))
case (Some(_), None) => throw new InternalError(
"ExpandTemplates: expanding a template with no template definition"
)
}
}
+
+ /** Expand a template */
+ private def expandTemplate(
+ a: Analysis,
+ aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
+ ): ResultAnnotatedNode[Ast.SpecTemplateExpand] = {
+ val (pre, node, post) = aNode
+ val data = node.data
+ for {
+ // Look up the template def
+ tmpl <- a.getTemplateSymbol(data.template.id)
+
+ // Clone the template body, recording the expansion node so that any
+ // nested expansion specifier is rejected and so that cloned nodes
+ // point back at the expansion site.
+ // Record the template definition too for diagnostics.
+ members <- transformList(
+ a.copy(
+ templateExpansionId = Some(node.id),
+ templateDefinitionId = Some(tmpl.node._2.id)
+ ),
+ tmpl.node._2.data.members,
+ matchModuleMember
+ )
+ } yield {
+ // Paste the expanded template body into the expansion specifier
+ ((), (pre, AstNode.create(data.copy(members = Some(members._2.flatten)), node.id), post))
+ }
+ }
+
}
diff --git a/compiler/tools/fpp-syntax/test/template.ref.txt b/compiler/tools/fpp-syntax/test/template.ref.txt
index 070cbb1d5..cecd64f59 100644
--- a/compiler/tools/fpp-syntax/test/template.ref.txt
+++ b/compiler/tools/fpp-syntax/test/template.ref.txt
@@ -53,12 +53,7 @@ def module
type name qual ident Type
instance template arg
qual ident .instance1
- def array
- ident Arr
- size literal int 3
- type name qual ident TypeParam
- def topology
- ident Top
- spec interface instance
- qual ident inst
+ def constant
+ ident a
+ literal int 0
@< Expanded expansion specifier
From fd871c164c88b1f52e4ad5c8f34ddf956aaca574 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 20:24:27 -0700
Subject: [PATCH 07/51] Revise spec
Refactor implementation
---
compiler/lib/src/main/scala/analysis/Analysis.scala | 8 ++++----
.../main/scala/analysis/Analyzers/ModuleAnalyzer.scala | 3 ++-
.../CheckSemantics/ExpandSyntaxAndEnterSymbols.scala | 2 ++
docs/fpp-spec.html | 7 ++++++-
docs/spec/Specifiers/Template-Expansion-Specifiers.adoc | 4 ++++
docs/wiki/Check-Template-Uses.asciidoc | 2 +-
6 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/Analysis.scala b/compiler/lib/src/main/scala/analysis/Analysis.scala
index d50c4c8cf..21ab1ba20 100644
--- a/compiler/lib/src/main/scala/analysis/Analysis.scala
+++ b/compiler/lib/src/main/scala/analysis/Analysis.scala
@@ -88,14 +88,14 @@ case class Analysis(
tlmPacketSet: Option[TlmPacketSet] = None,
/** The mapping from nodes to implied uses */
impliedUseMap: Map[AstNode.Id, ImpliedUse.Uses] = Map(),
+ /** Node ID of the current template definition */
+ templateDefinitionId: Option[AstNode.Id] = None,
/** Node ID of the current template expansion */
templateExpansionId: Option[AstNode.Id] = None,
- /** Maps template expansion AST nodes to their expansions */
- templateExpansionMap: Map[AstNode.Id, TemplateExpansion] = Map(),
/** The current template expansion */
templateExpansion: Option[TemplateExpansion] = None,
- /** Node ID of the current template definition */
- templateDefinitionId: Option[AstNode.Id] = None,
+ /** Mapping from template expansion nodes to their expansions */
+ templateExpansionMap: Map[AstNode.Id, TemplateExpansion] = Map(),
/** The set of symbols defined with a dictionary specifier */
dictionarySymbolSet: Set[Symbol] = Set(),
/** The mapping from system symbols to systems */
diff --git a/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala b/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala
index bca23d984..77d40738e 100644
--- a/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala
+++ b/compiler/lib/src/main/scala/analysis/Analyzers/ModuleAnalyzer.scala
@@ -32,7 +32,8 @@ trait ModuleAnalyzer extends Analyzer {
yield a2.copy(templateExpansion = a.templateExpansion)
case None =>
// This node has not yet been expanded by analysis.
- // The expansion is provided in an expand { ... } clause.
+ // The expansion is provided in the source model, in the form
+ // expand T { ... }.
Right(a)
}
}
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
index b2351b7b9..8e4447508 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
@@ -16,6 +16,8 @@ object ExpandSyntaxAndEnterSymbols {
(a, tul) <- ResolveSpecInclude.transUnitList(a, tul)
tul <- AddStateEnums.transUnitList(tul)
a <- EnterSymbols.visitList(a, tul, EnterSymbols.transUnit)
+ // TODO: CheckTemplateDefinitions
+ // TODO: CheckTemplateExpansions
a <- CheckTemplateUses.visitList(a, tul, CheckTemplateUses.transUnit)
(_, tul) <- ExpandTemplates.transformList(a, tul, ExpandTemplates.transUnit)
a <- EnterTemplateExpansionSymbols.visitList(a, tul, EnterTemplateExpansionSymbols.transUnit)
diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html
index fcb52cc52..c96f47e6b 100644
--- a/docs/fpp-spec.html
+++ b/docs/fpp-spec.html
@@ -9374,6 +9374,11 @@ 7.19.2. Semantics
+
+If module-member-sequence is present, then it must not
+transitively contain any module
+template definitions or template expansion specifiers.
+
@@ -14573,7 +14578,7 @@
diff --git a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
index 49b27b09c..19411a011 100644
--- a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
+++ b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
@@ -84,6 +84,10 @@ template argument.
... When _p_ is a type template parameter, _B_
is called a *type parameter definition*.
+. If _module-member-sequence_ is present, then it must not
+transitively contain any <> or template expansion specifiers.
+
==== Examples
[source,fpp]
diff --git a/docs/wiki/Check-Template-Uses.asciidoc b/docs/wiki/Check-Template-Uses.asciidoc
index 7a2fd175d..b5d383b05 100644
--- a/docs/wiki/Check-Template-Uses.asciidoc
+++ b/docs/wiki/Check-Template-Uses.asciidoc
@@ -1,5 +1,5 @@
This algorithm traverses a source model and checks that each use
-of a module template definition refers to a valid template definition.
+of a module template definition refers to a template definition.
It also constructs the use-def map entries for template expansion
specifiers.
From 1464b48c1dac8a08d8b9ac6f3a39a1b176e621f5 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 21:11:03 -0700
Subject: [PATCH 08/51] Refactor error checking
---
.../src/main/scala/analysis/Analysis.scala | 2 +-
.../CheckSemantics/CheckTemplateDefs.scala | 40 ++++
.../ExpandSyntaxAndEnterSymbols.scala | 2 +-
.../scala/transform/ExpandTemplates.scala | 29 ++-
compiler/lib/src/main/scala/util/Error.scala | 188 +++++++++---------
.../test/template/composition_invalid.ref.txt | 2 +-
.../test/template/invalid_nested.ref.txt | 2 +-
7 files changed, 145 insertions(+), 120 deletions(-)
create mode 100644 compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
diff --git a/compiler/lib/src/main/scala/analysis/Analysis.scala b/compiler/lib/src/main/scala/analysis/Analysis.scala
index 21ab1ba20..67ecbca15 100644
--- a/compiler/lib/src/main/scala/analysis/Analysis.scala
+++ b/compiler/lib/src/main/scala/analysis/Analysis.scala
@@ -89,7 +89,7 @@ case class Analysis(
/** The mapping from nodes to implied uses */
impliedUseMap: Map[AstNode.Id, ImpliedUse.Uses] = Map(),
/** Node ID of the current template definition */
- templateDefinitionId: Option[AstNode.Id] = None,
+ templateDefId: Option[AstNode.Id] = None,
/** Node ID of the current template expansion */
templateExpansionId: Option[AstNode.Id] = None,
/** The current template expansion */
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
new file mode 100644
index 000000000..a564e713d
--- /dev/null
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
@@ -0,0 +1,40 @@
+package fpp.compiler.analysis
+
+import fpp.compiler.ast._
+import fpp.compiler.util._
+
+/** Check template definitions */
+object CheckTemplateDefs
+ extends Analyzer
+ with ModuleAnalyzer
+{
+
+ override def defModuleTemplateAnnotatedNode(
+ a: Analysis,
+ aNode: Ast.Annotated[AstNode[Ast.DefModuleTemplate]]
+ ) = {
+ val (_, node, _) = aNode
+ val data = node.data
+ for {
+ _ <- a.templateDefId match {
+ case Some(defId) => Left(
+ SemanticError.TemplateDefError(
+ Locations.get(node.id),
+ "module template definitions cannot be nested",
+ Locations.get(defId)
+ )
+ )
+ case None => Right(a)
+ }
+ a <- Right(a.copy(templateDefId = Some(node.id)))
+ a <- visitList(a, data.members, matchModuleMember)
+ a <- Right(a.copy(templateDefId = None))
+ } yield a
+ }
+
+ override def specTemplateExpandAnnotatedNode(
+ a: Analysis,
+ aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
+ ) = Right(a)
+
+}
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
index 8e4447508..36ff9b9b3 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
@@ -16,7 +16,7 @@ object ExpandSyntaxAndEnterSymbols {
(a, tul) <- ResolveSpecInclude.transUnitList(a, tul)
tul <- AddStateEnums.transUnitList(tul)
a <- EnterSymbols.visitList(a, tul, EnterSymbols.transUnit)
- // TODO: CheckTemplateDefinitions
+ a <- CheckTemplateDefs.visitList(a, tul, CheckTemplateDefs.transUnit)
// TODO: CheckTemplateExpansions
a <- CheckTemplateUses.visitList(a, tul, CheckTemplateUses.transUnit)
(_, tul) <- ExpandTemplates.transformList(a, tul, ExpandTemplates.transUnit)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 06b34dbc9..09d8919a0 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -1066,18 +1066,10 @@ object ExpandTemplates extends AstTransformer
}
for {
- // Validate no nested template
- _ <- a.templateDefinitionId match {
- case Some(parent) => Left(SemanticError.NestedTemplateDefinition(
- Locations.get(aNode._2.id),
- Locations.get(parent)
- ))
- case None => Right(())
- }
- a <- Right(a.copy(templateDefinitionId = Some(node.id)))
+ a <- Right(a.copy(templateDefId = Some(node.id)))
params <- transformList(a, data.params, templateParam)
members <- transformList(a, data.members, matchModuleMember)
- a <- Right(a.copy(templateDefinitionId = None))
+ a <- Right(a.copy(templateDefId = None))
}
yield {
val (_, params1) = params
@@ -1107,7 +1099,7 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecTemplateExpand] = {
val (_, node, _) = aNode
val data = node.data
- (a.templateExpansionId, a.templateDefinitionId) match {
+ (a.templateExpansionId, a.templateDefId) match {
case (None, None) =>
// Not inside a template: expand if needed
data.members match {
@@ -1116,12 +1108,15 @@ object ExpandTemplates extends AstTransformer
// Members are not there; expand
case None => expandTemplate(a, aNode)
}
- case (_, Some(templateDefinitionId)) =>
+ case (_, Some(templateDefId)) =>
// The expansion specifier is nested inside a template body
- Left(SemanticError.TemplateExpansionInTemplate(
- Locations.get(node.id),
- Locations.get(templateDefinitionId)
- ))
+ Left(
+ SemanticError.TemplateDefError(
+ Locations.get(node.id),
+ "template expansion specifiers cannot appear inside a module template",
+ Locations.get(templateDefId)
+ )
+ )
case (Some(_), None) => throw new InternalError(
"ExpandTemplates: expanding a template with no template definition"
)
@@ -1146,7 +1141,7 @@ object ExpandTemplates extends AstTransformer
members <- transformList(
a.copy(
templateExpansionId = Some(node.id),
- templateDefinitionId = Some(tmpl.node._2.id)
+ templateDefId = Some(tmpl.node._2.id)
),
tmpl.node._2.data.members,
matchModuleMember
diff --git a/compiler/lib/src/main/scala/util/Error.scala b/compiler/lib/src/main/scala/util/Error.scala
index 0d66e7217..f17f1e8bb 100644
--- a/compiler/lib/src/main/scala/util/Error.scala
+++ b/compiler/lib/src/main/scala/util/Error.scala
@@ -270,18 +270,18 @@ sealed trait Error {
System.err.println("conflicting port number is here:")
System.err.println(p2Loc)
printMatchingLoc(matchingLoc)
- case SemanticError.WrongNumberOfTemplateArguments(
- expandLoc: Location,
- defLoc: Location,
- expandLength: Number,
- defLength: Number,
+ case SemanticError.InterfaceImplements(
+ loc,
+ err
) =>
- val parameters = if defLength == 1 then "argument" else "arguments"
- Error.print (Some(expandLoc)) (
- s"expected $defLength template $parameters, got $expandLength"
- )
- System.err.println("template defined here:")
- System.err.println(defLoc)
+ Error.print (Some(loc)) ("port interface not implemented")
+ err.print
+ case SemanticError.InterfaceImport(
+ importLoc,
+ err
+ ) =>
+ Error.print (Some(importLoc)) (s"failed to import interface")
+ err.print
case SemanticError.InvalidTemplateArg(
paramName: String,
argLoc: Location,
@@ -291,30 +291,6 @@ sealed trait Error {
Error.print (Some(argLoc)) (s"invalid argument for template parameter $paramName: $msg")
System.err.println("template parameter is defined here:")
System.err.println(paramLoc)
- case SemanticError.TemplateParameterConflict(
- paramName: String,
- paramLoc: Location,
- defLoc: Location,
- ) =>
- Error.print (Some(paramLoc)) (
- s"template parameter $paramName conflicts with a definition in the template body"
- )
- System.err.println("conflicting definition is here:")
- System.err.println(defLoc)
- case SemanticError.NestedTemplateDefinition(
- nestedLoc: Location,
- parentLoc: Location
- ) =>
- Error.print (Some(nestedLoc)) ("module template definitions cannot be nested")
- System.err.println("parent template defined here:")
- System.err.println(parentLoc)
- case SemanticError.TemplateExpansionInTemplate(
- expandLoc: Location,
- templateLoc: Location
- ) =>
- Error.print (Some(expandLoc)) ("template expansion specifiers cannot appear inside a module template")
- System.err.println("enclosing template defined here:")
- System.err.println(templateLoc)
case SemanticError.MissingAsync(kind, loc) =>
Error.print (Some(loc)) (s"$kind component must have async input")
case SemanticError.MissingConnection(loc, matchingLoc) =>
@@ -349,6 +325,16 @@ sealed trait Error {
}
case SemanticError.PassiveStateMachine(loc) =>
Error.print (Some(loc)) ("passive component may not have a state machine instance")
+ case SemanticError.PortInterfaceMissingPort(
+ loc
+ ) =>
+ Error.print (Some(loc)) ("port instance missing")
+ case SemanticError.PortInterfaceInvalidPort(
+ loc,
+ defLoc
+ ) =>
+ Error.print (Some(loc)) ("port instance does not match definition in interface:")
+ System.err.println(defLoc)
case SemanticError.RedefinedSymbol(name, loc, prevLoc) =>
Error.print (Some(loc)) (s"redefinition of symbol ${name}")
System.err.println("previous definition is here:")
@@ -387,6 +373,24 @@ sealed trait Error {
Error.print (Some(loc)) (s"state machine has too many leaf states")
case SemanticError.StateMachine.UnreachableNode(name, loc) =>
Error.print (Some(loc)) (s"$name is unreachable")
+ case SemanticError.TemplateParameterConflict(
+ paramName: String,
+ paramLoc: Location,
+ defLoc: Location,
+ ) =>
+ Error.print (Some(paramLoc)) (
+ s"template parameter $paramName conflicts with a definition in the template body"
+ )
+ System.err.println("conflicting definition is here:")
+ System.err.println(defLoc)
+ case SemanticError.TemplateDefError(
+ loc: Location,
+ msg: String,
+ defLoc: Location
+ ) =>
+ Error.print (Some(loc)) (msg)
+ System.err.println("enclosing template is defined here:")
+ System.err.println(defLoc)
case SemanticError.TooManyOutputPorts(loc, numPorts, arraySize, instanceLoc) =>
Error.print (Some(loc)) (s"too many ports connected here (found $numPorts, max is $arraySize)")
System.err.println("for this component instance:")
@@ -395,29 +399,19 @@ sealed trait Error {
case SemanticError.UndefinedSymbol(name, symbolKind, loc) =>
Error.print (Some(loc)) (s"symbol ${name} is not defined")
printNote(s"looking for a $symbolKind here")
- case SemanticError.InterfaceImport(
- importLoc,
- err
- ) =>
- Error.print (Some(importLoc)) (s"failed to import interface")
- err.print
- case SemanticError.PortInterfaceMissingPort(
- loc
- ) =>
- Error.print (Some(loc)) ("port instance missing")
- case SemanticError.PortInterfaceInvalidPort(
- loc,
- defLoc
+ case SemanticError.UseDefCycle(loc, msg) => Error.print (Some(loc)) (msg)
+ case SemanticError.WrongNumberOfTemplateArguments(
+ expandLoc: Location,
+ defLoc: Location,
+ expandLength: Number,
+ defLength: Number,
) =>
- Error.print (Some(loc)) ("port instance does not match definition in interface:")
+ val parameters = if defLength == 1 then "argument" else "arguments"
+ Error.print (Some(expandLoc)) (
+ s"expected $defLength template $parameters, got $expandLength"
+ )
+ System.err.println("template defined here:")
System.err.println(defLoc)
- case SemanticError.InterfaceImplements(
- loc,
- err
- ) =>
- Error.print (Some(loc)) ("port interface not implemented")
- err.print
- case SemanticError.UseDefCycle(loc, msg) => Error.print (Some(loc)) (msg)
case XmlError.ParseError(file, msg) => Error.printXml (file) (msg)
case XmlError.SemanticError(file, msg) => Error.printXml (file) (msg)
case AnnotatedError(error, notes) =>
@@ -627,6 +621,16 @@ object SemanticError {
specifiedPath: String,
actualLoc: Location
) extends Error
+ /** Error while importing an interface */
+ final case class InterfaceImport(
+ importLoc: Location,
+ err: Error
+ ) extends Error
+ /** Error while checking if instance implements interface */
+ final case class InterfaceImplements(
+ loc: Location,
+ err: Error
+ ) extends Error
/** No member in anonymous struct type */
final case class InvalidAnonStructMember(
memberName: String,
@@ -748,6 +752,13 @@ object SemanticError {
msg: String,
defLoc: Location
) extends Error
+ /** Template argument of the wrong kind */
+ final case class InvalidTemplateArg(
+ paramName: String,
+ argLoc: Location,
+ paramLoc: Location,
+ msg: String,
+ ) extends Error
/** Invalid telemetry channel identifier name */
final case class InvalidTlmChannelName(
loc: Location,
@@ -770,36 +781,6 @@ object SemanticError {
p2Number: Int,
matchingLoc: Location
) extends Error
- /** Wrong number of template arguments */
- final case class WrongNumberOfTemplateArguments(
- expandLoc: Location,
- defLoc: Location,
- expandLength: Number,
- defLength: Number,
- ) extends Error
- /** Template argument of the wrong kind */
- final case class InvalidTemplateArg(
- paramName: String,
- argLoc: Location,
- paramLoc: Location,
- msg: String,
- ) extends Error
- /** Template parameter conflicts with a definition in the template body */
- final case class TemplateParameterConflict(
- paramName: String,
- paramLoc: Location,
- defLoc: Location,
- ) extends Error
- /** Nested template definition */
- final case class NestedTemplateDefinition(
- nestedLoc: Location,
- parentLoc: Location,
- ) extends Error
- /** Template expansion specifier nested inside a template */
- final case class TemplateExpansionInTemplate(
- expandLoc: Location,
- templateLoc: Location,
- ) extends Error
/** Missing async input */
final case class MissingAsync(kind: String, loc: Location) extends Error
/** Missing connection */
@@ -832,11 +813,9 @@ object SemanticError {
name2: String,
loc2: Location
) extends Error
- /** Error while importing an interface */
- final case class InterfaceImport(
- importLoc: Location,
- err: Error
- ) extends Error
+ /** Passive async input */
+ final case class PassiveAsync(loc: Location, importLocs: List[Location]) extends Error
+ final case class PassiveStateMachine(loc: Location) extends Error
/** A port is missing from a port interface */
final case class PortInterfaceMissingPort(
loc: Location
@@ -846,14 +825,6 @@ object SemanticError {
loc: Location,
defLoc: Location
) extends Error
- /** Error while checking if instance implements interface */
- final case class InterfaceImplements(
- loc: Location,
- err: Error
- ) extends Error
- /** Passive async input */
- final case class PassiveAsync(loc: Location, importLocs: List[Location]) extends Error
- final case class PassiveStateMachine(loc: Location) extends Error
/** Redefined symbol */
final case class RedefinedSymbol(
name: String,
@@ -906,6 +877,18 @@ object SemanticError {
loc: Location
) extends Error
}
+ /** Error in template definition */
+ final case class TemplateDefError(
+ loc: Location,
+ msg: String,
+ defLoc: Location
+ ) extends Error
+ /** Template parameter conflicts with a definition in the template body */
+ final case class TemplateParameterConflict(
+ paramName: String,
+ paramLoc: Location,
+ defLoc: Location,
+ ) extends Error
/** Too many output ports */
final case class TooManyOutputPorts(
loc: Location,
@@ -919,6 +902,13 @@ object SemanticError {
final case class UndefinedSymbol(name: String, symbolKind: String, loc: Location) extends Error
/** Use-def cycle */
final case class UseDefCycle(loc: Location, msg: String) extends Error
+ /** Wrong number of template arguments */
+ final case class WrongNumberOfTemplateArguments(
+ expandLoc: Location,
+ defLoc: Location,
+ expandLength: Number,
+ defLength: Number,
+ ) extends Error
}
/** An F Prime XML error */
diff --git a/compiler/tools/fpp-check/test/template/composition_invalid.ref.txt b/compiler/tools/fpp-check/test/template/composition_invalid.ref.txt
index 1ebb3e497..9df63fadb 100644
--- a/compiler/tools/fpp-check/test/template/composition_invalid.ref.txt
+++ b/compiler/tools/fpp-check/test/template/composition_invalid.ref.txt
@@ -3,7 +3,7 @@ fpp-check
expand T1(constant p)
^
error: template expansion specifiers cannot appear inside a module template
-enclosing template defined here:
+enclosing template is defined here:
[ local path prefix ]/compiler/tools/fpp-check/test/template/composition_invalid.fpp:7.1
module template T2(
^
diff --git a/compiler/tools/fpp-check/test/template/invalid_nested.ref.txt b/compiler/tools/fpp-check/test/template/invalid_nested.ref.txt
index ec320733a..a20441bde 100644
--- a/compiler/tools/fpp-check/test/template/invalid_nested.ref.txt
+++ b/compiler/tools/fpp-check/test/template/invalid_nested.ref.txt
@@ -3,7 +3,7 @@ fpp-check
module template Inner(constant c2: U32) {
^
error: module template definitions cannot be nested
-parent template defined here:
+enclosing template is defined here:
[ local path prefix ]/compiler/tools/fpp-check/test/template/invalid_nested.fpp:1.1
module template Outer(constant c1: U32) {
^
From 450a092c3063cf1d5350e061217baed8621f5574 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 21:21:49 -0700
Subject: [PATCH 09/51] Revise CheckTemplateDefs
---
.../CheckSemantics/CheckTemplateDefs.scala | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
index a564e713d..61a92d176 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
@@ -35,6 +35,19 @@ object CheckTemplateDefs
override def specTemplateExpandAnnotatedNode(
a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
- ) = Right(a)
+ ) = {
+ val (_, node, _) = aNode
+ val data = node.data
+ a.templateDefId match {
+ case Some(defId) => Left(
+ SemanticError.TemplateDefError(
+ Locations.get(node.id),
+ "template expansion specifiers cannot appear inside a module template",
+ Locations.get(defId)
+ )
+ )
+ case None => Right(a)
+ }
+ }
}
From 5bd75f76c0528b7bba459673536f5de5dbb59576 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 21:35:20 -0700
Subject: [PATCH 10/51] Revise ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 32 ++++---------------
1 file changed, 7 insertions(+), 25 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 09d8919a0..b755a6be5 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -1099,27 +1099,11 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecTemplateExpand] = {
val (_, node, _) = aNode
val data = node.data
- (a.templateExpansionId, a.templateDefId) match {
- case (None, None) =>
- // Not inside a template: expand if needed
- data.members match {
- // Members are already there; nothing to do
- case Some(members) => Right((), aNode)
- // Members are not there; expand
- case None => expandTemplate(a, aNode)
- }
- case (_, Some(templateDefId)) =>
- // The expansion specifier is nested inside a template body
- Left(
- SemanticError.TemplateDefError(
- Locations.get(node.id),
- "template expansion specifiers cannot appear inside a module template",
- Locations.get(templateDefId)
- )
- )
- case (Some(_), None) => throw new InternalError(
- "ExpandTemplates: expanding a template with no template definition"
- )
+ data.members match {
+ // Members are already there; nothing to do
+ case Some(members) => Right((), aNode)
+ // Members are not there; expand
+ case None => expandTemplate(a, aNode)
}
}
@@ -1133,10 +1117,8 @@ object ExpandTemplates extends AstTransformer
for {
// Look up the template def
tmpl <- a.getTemplateSymbol(data.template.id)
-
- // Clone the template body, recording the expansion node so that any
- // nested expansion specifier is rejected and so that cloned nodes
- // point back at the expansion site.
+ // Clone the template body, recording the expansion node so that
+ // cloned nodes point back at the expansion site.
// Record the template definition too for diagnostics.
members <- transformList(
a.copy(
From 4ff5579dee2a89877bdcf2b6c451bb0393efbbf7 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 21:54:36 -0700
Subject: [PATCH 11/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 270 +++++++++---------
1 file changed, 134 insertions(+), 136 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index b755a6be5..afc70fef6 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -65,17 +65,6 @@ object ExpandTemplates extends AstTransformer
}
}
- def defaultNodeOpt[T](
- a: Analysis,
- node: Option[AstNode[T]]
- ): Result[Option[AstNode[T]]] =
- node match {
- case None => Right(((), None))
- case Some(node) =>
- for (result <- defaultNode(a, node))
- yield (result._1, Some(result._2))
- }
-
override def defaultAnnotatedNode[T](
a: In,
aNode: Ast.Annotated[AstNode[T]]
@@ -90,35 +79,6 @@ object ExpandTemplates extends AstTransformer
}
}
- inline def cloneNode[T](
- a: Analysis,
- node: AstNode[T],
- data: T
- ) =
- a.templateExpansionId match {
- case None => AstNode.create(data, node.id)
- case Some(expansionNode) => {
- val out = AstNode.create(data)
- val inLoc = Locations.get(node.id)
- Locations.put(out.id, Location(
- inLoc.file,
- inLoc.pos,
- inLoc.includingLoc,
- Some(Locations.get(expansionNode))
- ))
- out
- }
- }
-
- inline def cloneAnnotatedNode[T](
- a: Analysis,
- aNode: Ast.Annotated[AstNode[T]],
- data: T
- ) = {
- val (pre, node, post) = aNode
- (pre, cloneNode(a, node, data), post)
- }
-
override def exprArrayNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprArray): ResultNode[Ast.Expr] =
for { result <- transformList(a, e.elts, matchExprNode) }
yield {
@@ -191,12 +151,6 @@ object ExpandTemplates extends AstTransformer
}
}
- def qualIdentNode(
- a: In,
- node: AstNode[Ast.QualIdent]
- ): ResultNode[Ast.QualIdent] =
- Right(((), cloneQualIdentNode(a, node)))
-
override def exprStructNode(
a: Analysis,
node: AstNode[Ast.Expr],
@@ -226,20 +180,6 @@ object ExpandTemplates extends AstTransformer
))))
}
- def exprNodeOpt(
- a: In,
- node: Option[AstNode[Ast.Expr]]
- ): Result[Option[AstNode[Ast.Expr]]] =
- node match {
- case None => Right(((), None))
- case Some(value) =>
- for (result <- matchExprNode(a, value))
- yield {
- val (_, v1) = result
- ((), Some(v1))
- }
- }
-
override def typeNameStringNode(
a: In,
node: AstNode[Ast.TypeName],
@@ -257,17 +197,6 @@ object ExpandTemplates extends AstTransformer
}
}
- def typeNameNodeOpt(
- a: In,
- node: Option[AstNode[Ast.TypeName]]
- ): Result[Option[AstNode[Ast.TypeName]]] =
- node match {
- case None => Right(((), None))
- case Some(tn) =>
- for (result <- matchTypeName(a, tn))
- yield ((), Some(result._2))
- }
-
override def defAliasTypeAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
@@ -304,7 +233,7 @@ object ExpandTemplates extends AstTransformer
data.copy(
size = size._2,
eltType = eltType._2,
- default = default._2,
+ default = default,
format = cloneStringNodeOpt(a, data.format)
)
)
@@ -342,10 +271,10 @@ object ExpandTemplates extends AstTransformer
baseId=baseId._2,
implType=cloneStringNodeOpt(a, data.implType),
file=cloneStringNodeOpt(a, data.file),
- queueSize=queueSize._2,
- stackSize=stackSize._2,
- priority=priority._2,
- cpu=cpu._2,
+ queueSize=queueSize,
+ stackSize=stackSize,
+ priority=priority,
+ cpu=cpu,
initSpecs=initSpecs._2
)
)
@@ -380,7 +309,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for (value <- exprNodeOpt(a, data.value))
yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(value = value._2)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(value = value)))
}
override def defEnumAnnotatedNode(
@@ -393,9 +322,9 @@ object ExpandTemplates extends AstTransformer
constants <- transformList(a, data.constants, defEnumConstantAnnotatedNode)
default <- exprNodeOpt(a, data.default)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- typeName = typeName._2,
+ typeName = typeName,
constants = constants._2,
- default = default._2
+ default = default
)))
def formalAnnotatatedParam(
@@ -421,7 +350,7 @@ object ExpandTemplates extends AstTransformer
returnType <- typeNameNodeOpt(a, data.returnType)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
params = params._2,
- returnType = returnType._2
+ returnType = returnType
)))
override def defStateMachineAnnotatedNodeExternal(
@@ -457,7 +386,7 @@ object ExpandTemplates extends AstTransformer
for {
typeName <- typeNameNodeOpt(a, data.typeName)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName._2)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
}
def transitionExpr(
@@ -497,7 +426,7 @@ object ExpandTemplates extends AstTransformer
for {
typeName <- typeNameNodeOpt(a, data.typeName)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName._2)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
}
override def defSignalAnnotatedNode(
@@ -508,7 +437,7 @@ object ExpandTemplates extends AstTransformer
for {
typeName <- typeNameNodeOpt(a, data.typeName)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName._2)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
}
override def defStateAnnotatedNode(
@@ -577,27 +506,11 @@ object ExpandTemplates extends AstTransformer
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
signal = signal._2,
- guard = guard._2,
+ guard = guard,
transitionOrDo = transitionOrDo._2
)))
}
- def structTypeMemberAnnotatedNode(
- a: In,
- aNode: Ast.Annotated[AstNode[Ast.StructTypeMember]]
- ) =
- val data = aNode._2.data
- for {
- size <- exprNodeOpt(a, data.size)
- typeName <- matchTypeName(a, data.typeName)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- size = size._2,
- typeName = typeName._2,
- format = cloneStringNodeOpt(a, data.format)
- )))
- }
-
override def defStructAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefStruct]]
@@ -609,7 +522,7 @@ object ExpandTemplates extends AstTransformer
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
members = members._2,
- default = default._2
+ default = default
)))
}
@@ -654,9 +567,9 @@ object ExpandTemplates extends AstTransformer
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
params = params._2,
- opcode = opcode._2,
- priority = priority._2,
- queueFull = queueFull._2,
+ opcode = opcode,
+ priority = priority,
+ queueFull = queueFull,
)))
}
@@ -704,9 +617,9 @@ object ExpandTemplates extends AstTransformer
} yield {
((), connection.copy(
fromPort = fromPort._2,
- fromIndex = fromIndex._2,
+ fromIndex = fromIndex,
toPort = toPort._2,
- toIndex = toIndex._2,
+ toIndex = toIndex,
))
}
}
@@ -738,8 +651,8 @@ object ExpandTemplates extends AstTransformer
defaultPriority <- exprNodeOpt(a, data.defaultPriority)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- id = id._2,
- defaultPriority = defaultPriority._2,
+ id = id,
+ defaultPriority = defaultPriority,
)))
}
@@ -761,7 +674,7 @@ object ExpandTemplates extends AstTransformer
every <- exprNodeOpt(a, throttle.data.every)
} yield ((), Some(cloneNode(
a, throttle, throttle.data.copy(
- every = every._2,
+ every = every,
count = count._2,
)
)))
@@ -770,7 +683,7 @@ object ExpandTemplates extends AstTransformer
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
params = params._2,
- id = id._2,
+ id = id,
format = format._2,
throttle = throttle._2,
)))
@@ -808,7 +721,7 @@ object ExpandTemplates extends AstTransformer
priority <- exprNodeOpt(a, data.priority)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
params = params._2,
- priority = priority._2,
+ priority = priority,
)))
override def specLocAnnotatedNode(
@@ -837,24 +750,12 @@ object ExpandTemplates extends AstTransformer
saveOpcode <- exprNodeOpt(a, data.saveOpcode)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
typeName = typeName._2,
- default = default._2,
- id = id._2,
- setOpcode = setOpcode._2,
- saveOpcode = saveOpcode._2,
+ default = default,
+ id = id,
+ setOpcode = setOpcode,
+ saveOpcode = saveOpcode
)))
- def qualIdentNodeOpt(
- a: In,
- qi: Option[AstNode[Ast.QualIdent]]
- ): Result[Option[AstNode[Ast.QualIdent]]] = {
- qi match {
- case None => Right(((), None))
- case Some(value) =>
- for (result <- qualIdentNode(a, value))
- yield (((), Some(result._2)))
- }
- }
-
override def specPortInstanceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecPortInstance]]
@@ -869,10 +770,10 @@ object ExpandTemplates extends AstTransformer
queueFull <- defaultNodeOpt(a, data.queueFull)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- size = size._2,
+ size = size,
port = port._2,
- priority = priority._2,
- queueFull = queueFull._2
+ priority = priority,
+ queueFull = queueFull
)))
}
case data @ Ast.SpecPortInstance.Special(_, _, _, _, _) =>
@@ -881,8 +782,8 @@ object ExpandTemplates extends AstTransformer
queueFull <- defaultNodeOpt(a, data.queueFull)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- priority = priority._2,
- queueFull = queueFull._2
+ priority = priority,
+ queueFull = queueFull
)))
}
}
@@ -910,7 +811,7 @@ object ExpandTemplates extends AstTransformer
id <- exprNodeOpt(a, data.id)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
recordType = recordType._2,
- id = id._2
+ id = id
))))
override def specStateMachineInstanceAnnotatedNode(
@@ -923,7 +824,7 @@ object ExpandTemplates extends AstTransformer
priority <- exprNodeOpt(a, data.priority)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
stateMachine = stateMachine._2,
- priority = priority._2
+ priority = priority
))))
override def specTlmChannelAnnotatedNode(
@@ -949,7 +850,7 @@ object ExpandTemplates extends AstTransformer
high <- transformList(a, data.high, limit)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
typeName = typeName._2,
- id = id._2,
+ id = id,
format = cloneStringNodeOpt(a, data.format),
low = low._2,
high = high._2
@@ -988,7 +889,7 @@ object ExpandTemplates extends AstTransformer
group <- matchExprNode(a, data.group)
members <- transformList(a, data.members, tlmPacketMember)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- id = id._2,
+ id = id,
group = group._2,
members = members._2,
))))
@@ -1107,6 +1008,46 @@ object ExpandTemplates extends AstTransformer
}
}
+ private inline def cloneNode[T](
+ a: Analysis,
+ node: AstNode[T],
+ data: T
+ ) =
+ a.templateExpansionId match {
+ case None => AstNode.create(data, node.id)
+ case Some(expansionNode) => {
+ val out = AstNode.create(data)
+ val inLoc = Locations.get(node.id)
+ Locations.put(out.id, Location(
+ inLoc.file,
+ inLoc.pos,
+ inLoc.includingLoc,
+ Some(Locations.get(expansionNode))
+ ))
+ out
+ }
+ }
+
+ private inline def cloneAnnotatedNode[T](
+ a: Analysis,
+ aNode: Ast.Annotated[AstNode[T]],
+ data: T
+ ) = {
+ val (pre, node, post) = aNode
+ (pre, cloneNode(a, node, data), post)
+ }
+
+ private def defaultNodeOpt[T](
+ a: Analysis,
+ node: Option[AstNode[T]]
+ ): Result.Result[Option[AstNode[T]]] =
+ node match {
+ case None => Right(None)
+ case Some(node) =>
+ for ((_, node) <- defaultNode(a, node))
+ yield Some(node)
+ }
+
/** Expand a template */
private def expandTemplate(
a: Analysis,
@@ -1134,4 +1075,61 @@ object ExpandTemplates extends AstTransformer
}
}
+ private def exprNodeOpt(
+ a: In,
+ node: Option[AstNode[Ast.Expr]]
+ ): Result.Result[Option[AstNode[Ast.Expr]]] =
+ node match {
+ case None => Right(None)
+ case Some(value) =>
+ for ((_, result) <- matchExprNode(a, value))
+ yield Some(result)
+ }
+
+ private def qualIdentNode(
+ a: In,
+ node: AstNode[Ast.QualIdent]
+ ): ResultNode[Ast.QualIdent] =
+ Right(((), cloneQualIdentNode(a, node)))
+
+ private def qualIdentNodeOpt(
+ a: In,
+ qi: Option[AstNode[Ast.QualIdent]]
+ ): Result[Option[AstNode[Ast.QualIdent]]] = {
+ qi match {
+ case None => Right(((), None))
+ case Some(value) =>
+ for (result <- qualIdentNode(a, value))
+ yield (((), Some(result._2)))
+ }
+ }
+
+ private def structTypeMemberAnnotatedNode(
+ a: In,
+ aNode: Ast.Annotated[AstNode[Ast.StructTypeMember]]
+ ) =
+ val data = aNode._2.data
+ for {
+ size <- exprNodeOpt(a, data.size)
+ typeName <- matchTypeName(a, data.typeName)
+ } yield {
+ ((), cloneAnnotatedNode(a, aNode, data.copy(
+ size = size,
+ typeName = typeName._2,
+ format = cloneStringNodeOpt(a, data.format)
+ )))
+ }
+
+ private def typeNameNodeOpt(
+ a: In,
+ node: Option[AstNode[Ast.TypeName]]
+ ): Result.Result[Option[AstNode[Ast.TypeName]]] =
+ node match {
+ case None => Right(None)
+ case Some(tn) =>
+ for ((_, tn) <- matchTypeName(a, tn))
+ yield Some(tn)
+ }
+
+
}
From a43331612c53447b452ae68793955538dd53d208 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 22:19:00 -0700
Subject: [PATCH 12/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 82 ++++++++++---------
1 file changed, 43 insertions(+), 39 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index afc70fef6..661569d46 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -255,12 +255,12 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
component <- Right(cloneQualIdentNode(a, data.component))
- baseId <- matchExprNode(a, data.baseId)
+ (_, baseId) <- matchExprNode(a, data.baseId)
queueSize <- exprNodeOpt(a, data.queueSize)
stackSize <- exprNodeOpt(a, data.stackSize)
priority <- exprNodeOpt(a, data.priority)
cpu <- exprNodeOpt(a, data.cpu)
- initSpecs <- transformList(a, data.initSpecs, specInitAnnotatedNode)
+ (_, initSpecs) <- transformList(a, data.initSpecs, specInitAnnotatedNode)
} yield {
(
(),
@@ -268,14 +268,14 @@ object ExpandTemplates extends AstTransformer
a, aNode,
data.copy(
component=component,
- baseId=baseId._2,
+ baseId=baseId,
implType=cloneStringNodeOpt(a, data.implType),
file=cloneStringNodeOpt(a, data.file),
queueSize=queueSize,
stackSize=stackSize,
priority=priority,
cpu=cpu,
- initSpecs=initSpecs._2
+ initSpecs=initSpecs
)
)
)
@@ -398,7 +398,7 @@ object ExpandTemplates extends AstTransformer
target <- qualIdentNode(a, node.data.target)
} yield ((), cloneNode(a, node, node.data.copy(
actions = actions._2,
- target = target._2,
+ target = target,
)))
override def defChoiceAnnotatedNode(
@@ -481,19 +481,6 @@ object ExpandTemplates extends AstTransformer
((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions._2)))
}
- def transitionOrDo(
- a: In,
- transitionOrDo: Ast.TransitionOrDo
- ) =
- transitionOrDo match
- case Ast.TransitionOrDo.Transition(transition) =>
- for (result <- transitionExpr(a, transition))
- yield (result._1, Ast.TransitionOrDo.Transition(result._2))
- case Ast.TransitionOrDo.Do(actions) =>
- for (result <- transformList(a, actions, defaultNode))
- yield (result._1, Ast.TransitionOrDo.Do(result._2))
-
-
override def specStateTransitionAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecStateTransition]]
@@ -507,7 +494,7 @@ object ExpandTemplates extends AstTransformer
((), cloneAnnotatedNode(a, aNode, data.copy(
signal = signal._2,
guard = guard,
- transitionOrDo = transitionOrDo._2
+ transitionOrDo = transitionOrDo
)))
}
@@ -550,7 +537,7 @@ object ExpandTemplates extends AstTransformer
topology <- qualIdentNode(a, data.topology)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- topology = topology._2
+ topology = topology
)))
}
@@ -582,7 +569,7 @@ object ExpandTemplates extends AstTransformer
instance <- qualIdentNode(a, data.instance)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- instance = instance._2,
+ instance = instance,
)))
}
@@ -594,7 +581,7 @@ object ExpandTemplates extends AstTransformer
interfaceInstance <- qualIdentNode(a, pii.data.interfaceInstance)
portName <- defaultNode(a, pii.data.portName)
} yield ((), cloneNode(a, pii, pii.data.copy(
- interfaceInstance = interfaceInstance._2,
+ interfaceInstance = interfaceInstance,
portName = portName._2,
)))
}
@@ -634,13 +621,14 @@ object ExpandTemplates extends AstTransformer
case data @ Ast.SpecConnectionGraph.Pattern(_, source, targets) =>
for {
source <- qualIdentNode(a, source)
- targets <- transformList(a, targets, qualIdentNode)
+ (_, targets) <- transformList(a, targets, resultAdapter(qualIdentNode))
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- source = source._2,
- targets = targets._2
+ source = source,
+ targets = targets
)))
}
+
override def specContainerAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecContainer]]
@@ -670,12 +658,12 @@ object ExpandTemplates extends AstTransformer
case None => Right(((), None))
case Some(throttle) =>
for {
- count <- matchExprNode(a, throttle.data.count)
+ (_, count) <- matchExprNode(a, throttle.data.count)
every <- exprNodeOpt(a, throttle.data.every)
} yield ((), Some(cloneNode(
a, throttle, throttle.data.copy(
every = every,
- count = count._2,
+ count = count
)
)))
}
@@ -733,7 +721,7 @@ object ExpandTemplates extends AstTransformer
symbol <- qualIdentNode(a, data.symbol)
file <- defaultNode(a, data.file)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- symbol = symbol._2,
+ symbol = symbol,
file = file._2,
)))
@@ -771,7 +759,7 @@ object ExpandTemplates extends AstTransformer
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
size = size,
- port = port._2,
+ port = port,
priority = priority,
queueFull = queueFull
)))
@@ -823,7 +811,7 @@ object ExpandTemplates extends AstTransformer
stateMachine <- qualIdentNode(a, data.stateMachine)
priority <- exprNodeOpt(a, data.priority)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- stateMachine = stateMachine._2,
+ stateMachine = stateMachine,
priority = priority
))))
@@ -877,7 +865,7 @@ object ExpandTemplates extends AstTransformer
channelName <- defaultNode(a, node.data.channelName)
} yield ((), Ast.TlmPacketMember.TlmChannelIdentifier(
cloneNode(a, node, node.data.copy(
- componentInstance = componentInstance._2,
+ componentInstance = componentInstance,
channelName = channelName._2
))
))
@@ -919,7 +907,7 @@ object ExpandTemplates extends AstTransformer
componentInstance <- qualIdentNode(a, data.componentInstance)
channelName <- defaultNode(a, data.channelName)
} yield ((), cloneNode(a, node, data.copy(
- componentInstance = componentInstance._2,
+ componentInstance = componentInstance,
channelName = channelName._2
)))
@@ -939,7 +927,7 @@ object ExpandTemplates extends AstTransformer
for {
sym <- qualIdentNode(a, data.sym)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- sym = sym._2,
+ sym = sym
)))
override def defModuleTemplateAnnotatedNode(
@@ -962,7 +950,7 @@ object ExpandTemplates extends AstTransformer
Right(((), cloneAnnotatedNode(a, param, data)))
case data @ Ast.TemplateParam.Interface(_, interface) =>
for (interface <- qualIdentNode(a, interface))
- yield ((), cloneAnnotatedNode(a, param, data.copy(interface = interface._2)))
+ yield ((), cloneAnnotatedNode(a, param, data.copy(interface = interface)))
}
}
@@ -1089,21 +1077,25 @@ object ExpandTemplates extends AstTransformer
private def qualIdentNode(
a: In,
node: AstNode[Ast.QualIdent]
- ): ResultNode[Ast.QualIdent] =
- Right(((), cloneQualIdentNode(a, node)))
+ ): Result.Result[AstNode[Ast.QualIdent]] =
+ Right(cloneQualIdentNode(a, node))
private def qualIdentNodeOpt(
a: In,
qi: Option[AstNode[Ast.QualIdent]]
- ): Result[Option[AstNode[Ast.QualIdent]]] = {
+ ): Result.Result[Option[AstNode[Ast.QualIdent]]] = {
qi match {
- case None => Right(((), None))
+ case None => Right(None)
case Some(value) =>
for (result <- qualIdentNode(a, value))
- yield (((), Some(result._2)))
+ yield Some(result)
}
}
+ /** Adapt a simple result function to the form required by the visitor */
+ private def resultAdapter[A,B](f: (A, B) => Result.Result[B]) =
+ (a: A, b: B) => for (c <- f(a, b)) yield ((), c)
+
private def structTypeMemberAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.StructTypeMember]]
@@ -1120,6 +1112,18 @@ object ExpandTemplates extends AstTransformer
)))
}
+ private def transitionOrDo(
+ a: In,
+ transitionOrDo: Ast.TransitionOrDo
+ ) =
+ transitionOrDo match
+ case Ast.TransitionOrDo.Transition(transition) =>
+ for ((_, result) <- transitionExpr(a, transition))
+ yield Ast.TransitionOrDo.Transition(result)
+ case Ast.TransitionOrDo.Do(actions) =>
+ for ((_, result) <- transformList(a, actions, defaultNode))
+ yield Ast.TransitionOrDo.Do(result)
+
private def typeNameNodeOpt(
a: In,
node: Option[AstNode[Ast.TypeName]]
From a5e519bb78ab9098e9edf58942bea7103c2fd7c9 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 22:40:49 -0700
Subject: [PATCH 13/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 222 +++++++++---------
1 file changed, 110 insertions(+), 112 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 661569d46..c17101038 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -74,8 +74,8 @@ object ExpandTemplates extends AstTransformer
case None => Right((), aNode)
case Some(_) =>
val (pre, node, post) = aNode
- for (inter <- defaultNode(a, node))
- yield (inter._1, (pre, inter._2, post))
+ for ((_, inter) <- defaultNode(a, node))
+ yield ((), (pre, inter, post))
}
}
@@ -222,8 +222,8 @@ object ExpandTemplates extends AstTransformer
override def defArrayAnnotatedNode(a: In, aNode: Ast.Annotated[AstNode[Ast.DefArray]]): ResultAnnotatedNode[Ast.DefArray] =
val data = aNode._2.data
for {
- size <- matchExprNode(a, data.size)
- eltType <- matchTypeName(a, data.eltType)
+ (_, size) <- matchExprNode(a, data.size)
+ (_, eltType) <- matchTypeName(a, data.eltType)
default <- exprNodeOpt(a, data.default)
} yield {
(
@@ -231,8 +231,8 @@ object ExpandTemplates extends AstTransformer
cloneAnnotatedNode(
a, aNode,
data.copy(
- size = size._2,
- eltType = eltType._2,
+ size = size,
+ eltType = eltType,
default = default,
format = cloneStringNodeOpt(a, data.format)
)
@@ -319,27 +319,14 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
typeName <- typeNameNodeOpt(a, data.typeName)
- constants <- transformList(a, data.constants, defEnumConstantAnnotatedNode)
+ (_, constants) <- transformList(a, data.constants, defEnumConstantAnnotatedNode)
default <- exprNodeOpt(a, data.default)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
typeName = typeName,
- constants = constants._2,
+ constants = constants,
default = default
)))
- def formalAnnotatatedParam(
- a: In,
- aNode: Ast.Annotated[AstNode[Ast.FormalParam]]
- ) =
- val data = aNode._2.data
- for (ty <- matchTypeName(a, data.typeName))
- yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = ty._2)))
-
- def formalParamList(
- a: In,
- aNode: Ast.FormalParamList
- ) = transformList(a, aNode, formalAnnotatatedParam)
-
override def defPortAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefPort]]
@@ -349,7 +336,7 @@ object ExpandTemplates extends AstTransformer
params <- formalParamList(a, data.params)
returnType <- typeNameNodeOpt(a, data.returnType)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params._2,
+ params = params,
returnType = returnType
)))
@@ -389,32 +376,20 @@ object ExpandTemplates extends AstTransformer
((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
}
- def transitionExpr(
- a: In,
- node: AstNode[Ast.TransitionExpr]
- ): ResultNode[Ast.TransitionExpr] =
- for {
- actions <- transformList(a, node.data.actions, defaultNode)
- target <- qualIdentNode(a, node.data.target)
- } yield ((), cloneNode(a, node, node.data.copy(
- actions = actions._2,
- target = target,
- )))
-
override def defChoiceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefChoice]]
): ResultAnnotatedNode[Ast.DefChoice] =
val data = aNode._2.data
for {
- guard <- defaultNode(a, data.guard)
+ (_, guard) <- defaultNode(a, data.guard)
ifTransition <- transitionExpr(a, data.ifTransition)
elseTransition <- transitionExpr(a, data.elseTransition)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- guard = guard._2,
- ifTransition = ifTransition._2,
- elseTransition = elseTransition._2,
+ guard = guard,
+ ifTransition = ifTransition,
+ elseTransition = elseTransition
)))
}
@@ -456,7 +431,7 @@ object ExpandTemplates extends AstTransformer
for {
transition <- transitionExpr(a, data.transition)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(transition = transition._2)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(transition = transition)))
}
override def specStateEntryAnnotatedNode(
@@ -476,9 +451,9 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecStateExit] =
val data = aNode._2.data
for {
- actions <- transformList(a, data.actions, defaultNode)
+ (_, actions) <- transformList(a, data.actions, defaultNode)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions._2)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
}
override def specStateTransitionAnnotatedNode(
@@ -487,12 +462,12 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecStateTransition] =
val data = aNode._2.data
for {
- signal <- defaultNode(a, data.signal)
+ (_, signal) <- defaultNode(a, data.signal)
guard <- defaultNodeOpt(a, data.guard)
transitionOrDo <- transitionOrDo(a, data.transitionOrDo)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- signal = signal._2,
+ signal = signal,
guard = guard,
transitionOrDo = transitionOrDo
)))
@@ -504,11 +479,11 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefStruct] =
val data = aNode._2.data
for {
- members <- transformList(a, data.members, structTypeMemberAnnotatedNode)
+ (_, members) <- transformList(a, data.members, structTypeMemberAnnotatedNode)
default <- exprNodeOpt(a, data.default)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- members = members._2,
+ members = members,
default = default
)))
}
@@ -519,12 +494,12 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefTopology] =
val data = aNode._2.data
for {
- members <- transformList(a, data.members, matchTopologyMember)
- implements <- transformList(a, data.implements, (a, q) => Right(((), cloneQualIdentNode(a, q))))
+ (_, members) <- transformList(a, data.members, matchTopologyMember)
+ (_, implements) <- transformList(a, data.implements, (a, q) => Right(((), cloneQualIdentNode(a, q))))
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- members = members._2.flatten,
- implements = implements._2
+ members = members.flatten,
+ implements = implements
)))
}
@@ -553,7 +528,7 @@ object ExpandTemplates extends AstTransformer
queueFull <- defaultNodeOpt(a, data.queueFull)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params._2,
+ params = params,
opcode = opcode,
priority = priority,
queueFull = queueFull,
@@ -576,14 +551,14 @@ object ExpandTemplates extends AstTransformer
def portInstanceIdentifierNode(
a: In,
pii: AstNode[Ast.PortInstanceIdentifier]
- ): ResultNode[Ast.PortInstanceIdentifier] = {
+ ): Result.Result[AstNode[Ast.PortInstanceIdentifier]] = {
for {
interfaceInstance <- qualIdentNode(a, pii.data.interfaceInstance)
- portName <- defaultNode(a, pii.data.portName)
- } yield ((), cloneNode(a, pii, pii.data.copy(
+ (_, portName) <- defaultNode(a, pii.data.portName)
+ } yield cloneNode(a, pii, pii.data.copy(
interfaceInstance = interfaceInstance,
- portName = portName._2,
- )))
+ portName = portName
+ ))
}
override def specConnectionGraphAnnotatedNode(
@@ -603,9 +578,9 @@ object ExpandTemplates extends AstTransformer
toIndex <- exprNodeOpt(a, connection.toIndex)
} yield {
((), connection.copy(
- fromPort = fromPort._2,
+ fromPort = fromPort,
fromIndex = fromIndex,
- toPort = toPort._2,
+ toPort = toPort,
toIndex = toIndex,
))
}
@@ -614,9 +589,9 @@ object ExpandTemplates extends AstTransformer
data match {
case data @ Ast.SpecConnectionGraph.Direct(_, connections) =>
for {
- connections <- transformList(a, connections, connection)
+ (_, connections) <- transformList(a, connections, connection)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- connections = connections._2
+ connections = connections
)))
case data @ Ast.SpecConnectionGraph.Pattern(_, source, targets) =>
for {
@@ -652,28 +627,28 @@ object ExpandTemplates extends AstTransformer
for {
params <- formalParamList(a, data.params)
id <- exprNodeOpt(a, data.id)
- format <- defaultNode(a, data.format)
+ (_, format) <- defaultNode(a, data.format)
throttle <- {
data.throttle match {
- case None => Right(((), None))
+ case None => Right(None)
case Some(throttle) =>
for {
(_, count) <- matchExprNode(a, throttle.data.count)
every <- exprNodeOpt(a, throttle.data.every)
- } yield ((), Some(cloneNode(
+ } yield Some(cloneNode(
a, throttle, throttle.data.copy(
every = every,
count = count
)
- )))
+ ))
}
}
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params._2,
+ params = params,
id = id,
- format = format._2,
- throttle = throttle._2,
+ format = format,
+ throttle = throttle
)))
}
@@ -683,10 +658,8 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecInclude] =
val data = aNode._2.data
for {
- file <- defaultNode(a, data.file)
- } yield (file._1, cloneAnnotatedNode(a, aNode, data.copy(
- file = file._2,
- )))
+ (_, file) <- defaultNode(a, data.file)
+ } yield ((), cloneAnnotatedNode(a, aNode, data.copy(file = file)))
override def specInitAnnotatedNode(
a: In,
@@ -708,7 +681,7 @@ object ExpandTemplates extends AstTransformer
params <- formalParamList(a, data.params)
priority <- exprNodeOpt(a, data.priority)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params._2,
+ params = params,
priority = priority,
)))
@@ -719,10 +692,10 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
symbol <- qualIdentNode(a, data.symbol)
- file <- defaultNode(a, data.file)
+ (_, file) <- defaultNode(a, data.file)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
symbol = symbol,
- file = file._2,
+ file = file
)))
override def specParamAnnotatedNode(
@@ -731,13 +704,13 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecParam] =
val data = aNode._2.data
for {
- typeName <- matchTypeName(a, data.typeName)
+ (_, typeName) <- matchTypeName(a, data.typeName)
default <- exprNodeOpt(a, data.default)
id <- exprNodeOpt(a, data.id)
setOpcode <- exprNodeOpt(a, data.setOpcode)
saveOpcode <- exprNodeOpt(a, data.saveOpcode)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- typeName = typeName._2,
+ typeName = typeName,
default = default,
id = id,
setOpcode = setOpcode,
@@ -782,11 +755,11 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecPortMatching] =
val data = aNode._2.data
for {
- port1 <- defaultNode(a, data.port1)
- port2 <- defaultNode(a, data.port2)
+ (_, port1) <- defaultNode(a, data.port1)
+ (_, port2) <- defaultNode(a, data.port2)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- port1 = port1._2,
- port2 = port2._2
+ port1 = port1,
+ port2 = port2
))))
override def specRecordAnnotatedNode(
@@ -795,10 +768,10 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecRecord] =
val data = aNode._2.data
for {
- recordType <- matchTypeName(a, data.recordType)
+ (_, recordType) <- matchTypeName(a, data.recordType)
id <- exprNodeOpt(a, data.id)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- recordType = recordType._2,
+ recordType = recordType,
id = id
))))
@@ -826,22 +799,22 @@ object ExpandTemplates extends AstTransformer
): Result[Ast.SpecTlmChannel.Limit] = {
val (kind, value) = limit
for {
- kind <- defaultNode(a, kind)
- value <- matchExprNode(a, value)
- } yield (((), (kind._2, value._2)))
+ (_, kind) <- defaultNode(a, kind)
+ (_, value) <- matchExprNode(a, value)
+ } yield (((), (kind, value)))
}
for {
- typeName <- matchTypeName(a, data.typeName)
+ (_, typeName) <- matchTypeName(a, data.typeName)
id <- exprNodeOpt(a, data.id)
- low <- transformList(a, data.low, limit)
- high <- transformList(a, data.high, limit)
+ (_, low) <- transformList(a, data.low, limit)
+ (_, high) <- transformList(a, data.high, limit)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- typeName = typeName._2,
+ typeName = typeName,
id = id,
format = cloneStringNodeOpt(a, data.format),
- low = low._2,
- high = high._2
+ low = low,
+ high = high
))))
override def specTlmPacketAnnotatedNode(
@@ -855,18 +828,18 @@ object ExpandTemplates extends AstTransformer
): Result[Ast.TlmPacketMember] = {
member match {
case Ast.TlmPacketMember.SpecInclude(node) =>
- for (file <- defaultNode(a, node.data.file))
+ for ((_, file) <- defaultNode(a, node.data.file))
yield ((), Ast.TlmPacketMember.SpecInclude(
- cloneNode(a, node, node.data.copy(file = file._2))
+ cloneNode(a, node, node.data.copy(file = file))
))
case Ast.TlmPacketMember.TlmChannelIdentifier(node) =>
for {
componentInstance <- qualIdentNode(a, node.data.componentInstance)
- channelName <- defaultNode(a, node.data.channelName)
+ (_, channelName) <- defaultNode(a, node.data.channelName)
} yield ((), Ast.TlmPacketMember.TlmChannelIdentifier(
cloneNode(a, node, node.data.copy(
componentInstance = componentInstance,
- channelName = channelName._2
+ channelName = channelName
))
))
}
@@ -874,12 +847,12 @@ object ExpandTemplates extends AstTransformer
for {
id <- exprNodeOpt(a, data.id)
- group <- matchExprNode(a, data.group)
- members <- transformList(a, data.members, tlmPacketMember)
+ (_, group) <- matchExprNode(a, data.group)
+ (_, members) <- transformList(a, data.members, tlmPacketMember)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
id = id,
- group = group._2,
- members = members._2,
+ group = group,
+ members = members
))))
override def specTopPortAnnotatedNode(
@@ -890,7 +863,7 @@ object ExpandTemplates extends AstTransformer
for {
underlyingPort <- portInstanceIdentifierNode(a, data.underlyingPort)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- underlyingPort = underlyingPort._2,
+ underlyingPort = underlyingPort
)))
override def specTlmPacketSetAnnotatedNode(
@@ -905,18 +878,18 @@ object ExpandTemplates extends AstTransformer
val data = node.data
for {
componentInstance <- qualIdentNode(a, data.componentInstance)
- channelName <- defaultNode(a, data.channelName)
+ (_, channelName) <- defaultNode(a, data.channelName)
} yield ((), cloneNode(a, node, data.copy(
componentInstance = componentInstance,
- channelName = channelName._2
+ channelName = channelName
)))
for {
- members <- transformList(a, data.members, matchTlmPacketSetMember)
- omitted <- transformList(a, data.omitted, tlmChannelIdentifier)
+ (_, members) <- transformList(a, data.members, matchTlmPacketSetMember)
+ (_, omitted) <- transformList(a, data.omitted, tlmChannelIdentifier)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- members = members._2.flatten,
- omitted = omitted._2,
+ members = members.flatten,
+ omitted = omitted
)))
override def specInterfaceImportAnnotatedNode(
@@ -944,8 +917,8 @@ object ExpandTemplates extends AstTransformer
val (_, node, _) = param
node.data match {
case data @ Ast.TemplateParam.Constant(_, tn) =>
- for (tn <- matchTypeName(a, tn))
- yield ((), cloneAnnotatedNode(a, param, data.copy(typeName = tn._2)))
+ for ((_, tn) <- matchTypeName(a, tn))
+ yield ((), cloneAnnotatedNode(a, param, data.copy(typeName = tn)))
case data @ Ast.TemplateParam.Type(_) =>
Right(((), cloneAnnotatedNode(a, param, data)))
case data @ Ast.TemplateParam.Interface(_, interface) =>
@@ -1049,7 +1022,7 @@ object ExpandTemplates extends AstTransformer
// Clone the template body, recording the expansion node so that
// cloned nodes point back at the expansion site.
// Record the template definition too for diagnostics.
- members <- transformList(
+ (_, members) <- transformList(
a.copy(
templateExpansionId = Some(node.id),
templateDefId = Some(tmpl.node._2.id)
@@ -1059,7 +1032,7 @@ object ExpandTemplates extends AstTransformer
)
} yield {
// Paste the expanded template body into the expansion specifier
- ((), (pre, AstNode.create(data.copy(members = Some(members._2.flatten)), node.id), post))
+ ((), (pre, AstNode.create(data.copy(members = Some(members.flatten)), node.id), post))
}
}
@@ -1074,6 +1047,19 @@ object ExpandTemplates extends AstTransformer
yield Some(result)
}
+ private def formalAnnotatatedParam(
+ a: In,
+ aNode: Ast.Annotated[AstNode[Ast.FormalParam]]
+ ) =
+ val data = aNode._2.data
+ for ((_, ty) <- matchTypeName(a, data.typeName))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = ty)))
+
+ private def formalParamList(
+ a: In,
+ aNode: Ast.FormalParamList
+ ) = for ((_, node) <- transformList(a, aNode, formalAnnotatatedParam)) yield node
+
private def qualIdentNode(
a: In,
node: AstNode[Ast.QualIdent]
@@ -1103,22 +1089,34 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
size <- exprNodeOpt(a, data.size)
- typeName <- matchTypeName(a, data.typeName)
+ (_, typeName) <- matchTypeName(a, data.typeName)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
size = size,
- typeName = typeName._2,
+ typeName = typeName,
format = cloneStringNodeOpt(a, data.format)
)))
}
+ private def transitionExpr(
+ a: In,
+ node: AstNode[Ast.TransitionExpr]
+ ): Result.Result[AstNode[Ast.TransitionExpr]] =
+ for {
+ (_, actions) <- transformList(a, node.data.actions, defaultNode)
+ target <- qualIdentNode(a, node.data.target)
+ } yield cloneNode(a, node, node.data.copy(
+ actions = actions,
+ target = target,
+ ))
+
private def transitionOrDo(
a: In,
transitionOrDo: Ast.TransitionOrDo
) =
transitionOrDo match
case Ast.TransitionOrDo.Transition(transition) =>
- for ((_, result) <- transitionExpr(a, transition))
+ for (result <- transitionExpr(a, transition))
yield Ast.TransitionOrDo.Transition(result)
case Ast.TransitionOrDo.Do(actions) =>
for ((_, result) <- transformList(a, actions, defaultNode))
From 910aa238fa03fb0c72a5cde45bcce1c3c7e6de97 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 22:57:26 -0700
Subject: [PATCH 14/51] Refactor ExpandTemplates
---
.../ExpandSyntaxAndEnterSymbols.scala | 2 +-
.../scala/transform/ExpandTemplates.scala | 205 +++++++++---------
2 files changed, 99 insertions(+), 108 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
index 36ff9b9b3..2df372f13 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
@@ -19,7 +19,7 @@ object ExpandSyntaxAndEnterSymbols {
a <- CheckTemplateDefs.visitList(a, tul, CheckTemplateDefs.transUnit)
// TODO: CheckTemplateExpansions
a <- CheckTemplateUses.visitList(a, tul, CheckTemplateUses.transUnit)
- (_, tul) <- ExpandTemplates.transformList(a, tul, ExpandTemplates.transUnit)
+ tul <- ExpandTemplates.transformList(a, tul, ExpandTemplates.transUnit)
a <- EnterTemplateExpansionSymbols.visitList(a, tul, EnterTemplateExpansionSymbols.transUnit)
} yield (a, tul)
}
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index c17101038..bb24268c0 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -22,18 +22,17 @@ object ExpandTemplates extends AstTransformer
s: State,
list: List[A],
transform: (State, A) => Result[B]
- ): Result[List[B]] = {
- def helper(in: List[A], out: List[B]): Result[List[B]] = {
+ ): Result.Result[List[B]] = {
+ def helper(in: List[A], out: List[B]): Result.Result[List[B]] = {
in match {
- case Nil => Right(((), out))
+ case Nil => Right(out)
case head :: tail => transform(s, head) match {
case Left(e) => Left(e)
case Right((_, list)) => helper(tail, list :: out)
}
}
}
- for { pair <- helper(list, Nil) }
- yield ((), pair._2.reverse)
+ helper(list, Nil).map(_.reverse)
}
override def transUnit(
@@ -42,7 +41,7 @@ object ExpandTemplates extends AstTransformer
): Result[Ast.TransUnit] = {
for {
members <- transformList(a, tu.members, matchModuleMember)
- } yield (members._1, Ast.TransUnit(members._2.flatten))
+ } yield ((), Ast.TransUnit(members.flatten))
}
// Duplicate every node inside a template definition
@@ -82,8 +81,7 @@ object ExpandTemplates extends AstTransformer
override def exprArrayNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprArray): ResultNode[Ast.Expr] =
for { result <- transformList(a, e.elts, matchExprNode) }
yield {
- val (_, elts1) = result
- ((), cloneNode(a, node, Ast.ExprArray(elts1)))
+ ((), cloneNode(a, node, Ast.ExprArray(result)))
}
override def exprArraySubscriptNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprArraySubscript): ResultNode[Ast.Expr] =
@@ -122,35 +120,6 @@ object ExpandTemplates extends AstTransformer
((), cloneNode(a, node, Ast.ExprParen(value)))
}
- def structMember(
- a: Analysis,
- node: AstNode[Ast.StructMember]
- ) = {
- for (result <- matchExprNode(a, node.data.value))
- yield {
- val (_, value) = result
- ((), cloneNode(a, node, Ast.StructMember(
- node.data.name,
- value
- )))
- }
- }
-
- def cloneQualIdentNode(
- a: In,
- node: AstNode[Ast.QualIdent]
- ): AstNode[Ast.QualIdent] = {
- node.data match {
- case Ast.QualIdent.Qualified(qualifier, name) =>
- cloneNode(a, node, Ast.QualIdent.Qualified(
- cloneQualIdentNode(a, qualifier),
- cloneNode(a, name, name.data)
- ))
- case Ast.QualIdent.Unqualified(name, isAbsolute) =>
- cloneNode(a, node, Ast.QualIdent.Unqualified(name, isAbsolute))
- }
- }
-
override def exprStructNode(
a: Analysis,
node: AstNode[Ast.Expr],
@@ -158,17 +127,16 @@ object ExpandTemplates extends AstTransformer
) =
for { result <- transformList(a, e.members, structMember) }
yield {
- val (_, members1) = result
- ((), cloneNode(a, node, Ast.ExprStruct(members1)))
+ ((), cloneNode(a, node, Ast.ExprStruct(result)))
}
override def exprUnopNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprUnop) =
- for (ec <- matchExprNode(a, e.e))
- yield (ec._1, cloneNode(a, node, Ast.ExprUnop(e.op, ec._2)))
+ for ((_, ec) <- matchExprNode(a, e.e))
+ yield ((), cloneNode(a, node, Ast.ExprUnop(e.op, ec)))
override def exprSizeOfNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprSizeOf): ResultNode[Ast.Expr] =
- for (result <- matchTypeName(a, e.typeName))
- yield (result._1, cloneNode(a, node, Ast.ExprSizeOf(result._2)))
+ for ((_, result) <- matchTypeName(a, e.typeName))
+ yield ((), cloneNode(a, node, Ast.ExprSizeOf(result)))
override def typeNameQualIdentNode(
a: In,
@@ -210,15 +178,6 @@ object ExpandTemplates extends AstTransformer
))
}
- def cloneStringNodeOpt(
- a: In,
- node: Option[AstNode[String]]
- ): Option[AstNode[String]] =
- node match {
- case None => None
- case Some(value) => Some(cloneNode(a, value, value.data))
- }
-
override def defArrayAnnotatedNode(a: In, aNode: Ast.Annotated[AstNode[Ast.DefArray]]): ResultAnnotatedNode[Ast.DefArray] =
val data = aNode._2.data
for {
@@ -244,8 +203,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for (result <- transformList(a, data.members, matchComponentMember))
yield {
- val (_, members1) = result
- ((), cloneAnnotatedNode(a, aNode, data.copy(members = members1.flatten)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(members = result.flatten)))
}
override def defComponentInstanceAnnotatedNode(
@@ -260,7 +218,7 @@ object ExpandTemplates extends AstTransformer
stackSize <- exprNodeOpt(a, data.stackSize)
priority <- exprNodeOpt(a, data.priority)
cpu <- exprNodeOpt(a, data.cpu)
- (_, initSpecs) <- transformList(a, data.initSpecs, specInitAnnotatedNode)
+ initSpecs <- transformList(a, data.initSpecs, specInitAnnotatedNode)
} yield {
(
(),
@@ -285,8 +243,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for (result <- transformList(a, data.members, matchInterfaceMember))
yield {
- val (_, members1) = result
- ((), cloneAnnotatedNode(a, aNode, data.copy(members=members1)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(members=result)))
}
override def defConstantAnnotatedNode(
@@ -294,22 +251,12 @@ object ExpandTemplates extends AstTransformer
aNode: Ast.Annotated[AstNode[Ast.DefConstant]]
): ResultAnnotatedNode[Ast.DefConstant] =
val data = aNode._2.data
- for (value <- matchExprNode(a, data.value))
+ for ((_, value) <- matchExprNode(a, data.value))
yield {
((),
cloneAnnotatedNode(
a, aNode,
- data.copy(value = value._2)))
- }
-
- def defEnumConstantAnnotatedNode(
- a: In,
- aNode: Ast.Annotated[AstNode[Ast.DefEnumConstant]]
- ): ResultAnnotatedNode[Ast.DefEnumConstant] =
- val data = aNode._2.data
- for (value <- exprNodeOpt(a, data.value))
- yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(value = value)))
+ data.copy(value = value)))
}
override def defEnumAnnotatedNode(
@@ -319,7 +266,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
typeName <- typeNameNodeOpt(a, data.typeName)
- (_, constants) <- transformList(a, data.constants, defEnumConstantAnnotatedNode)
+ constants <- transformList(a, data.constants, defEnumConstantAnnotatedNode)
default <- exprNodeOpt(a, data.default)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
typeName = typeName,
@@ -353,7 +300,7 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefStateMachine] =
val data = aNode._2.data
for (result <- transformList(a, members, matchStateMachineMember))
- yield (result._1, cloneAnnotatedNode(a, aNode, data.copy(members = Some(result._2.flatten))))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = Some(result.flatten))))
override def defStateMachineAnnotatedNode(
a: In,
@@ -421,7 +368,7 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefState] =
val data = aNode._2.data
for (members <- transformList(a, data.members, matchStateMember))
- yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = members._2.flatten)))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = members.flatten)))
override def specInitialTransitionAnnotatedNode(
a: In,
@@ -442,7 +389,7 @@ object ExpandTemplates extends AstTransformer
for {
actions <- transformList(a, data.actions, defaultNode)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions._2)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
}
override def specStateExitAnnotatedNode(
@@ -451,7 +398,7 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.SpecStateExit] =
val data = aNode._2.data
for {
- (_, actions) <- transformList(a, data.actions, defaultNode)
+ actions <- transformList(a, data.actions, defaultNode)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
}
@@ -479,7 +426,7 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefStruct] =
val data = aNode._2.data
for {
- (_, members) <- transformList(a, data.members, structTypeMemberAnnotatedNode)
+ members <- transformList(a, data.members, structTypeMemberAnnotatedNode)
default <- exprNodeOpt(a, data.default)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
@@ -494,8 +441,8 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefTopology] =
val data = aNode._2.data
for {
- (_, members) <- transformList(a, data.members, matchTopologyMember)
- (_, implements) <- transformList(a, data.implements, (a, q) => Right(((), cloneQualIdentNode(a, q))))
+ members <- transformList(a, data.members, matchTopologyMember)
+ implements <- transformList(a, data.implements, (a, q) => Right(((), cloneQualIdentNode(a, q))))
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
members = members.flatten,
@@ -548,19 +495,6 @@ object ExpandTemplates extends AstTransformer
)))
}
- def portInstanceIdentifierNode(
- a: In,
- pii: AstNode[Ast.PortInstanceIdentifier]
- ): Result.Result[AstNode[Ast.PortInstanceIdentifier]] = {
- for {
- interfaceInstance <- qualIdentNode(a, pii.data.interfaceInstance)
- (_, portName) <- defaultNode(a, pii.data.portName)
- } yield cloneNode(a, pii, pii.data.copy(
- interfaceInstance = interfaceInstance,
- portName = portName
- ))
- }
-
override def specConnectionGraphAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecConnectionGraph]]
@@ -589,14 +523,14 @@ object ExpandTemplates extends AstTransformer
data match {
case data @ Ast.SpecConnectionGraph.Direct(_, connections) =>
for {
- (_, connections) <- transformList(a, connections, connection)
+ connections <- transformList(a, connections, connection)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
connections = connections
)))
case data @ Ast.SpecConnectionGraph.Pattern(_, source, targets) =>
for {
source <- qualIdentNode(a, source)
- (_, targets) <- transformList(a, targets, resultAdapter(qualIdentNode))
+ targets <- transformList(a, targets, resultAdapter(qualIdentNode))
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
source = source,
targets = targets
@@ -807,8 +741,8 @@ object ExpandTemplates extends AstTransformer
for {
(_, typeName) <- matchTypeName(a, data.typeName)
id <- exprNodeOpt(a, data.id)
- (_, low) <- transformList(a, data.low, limit)
- (_, high) <- transformList(a, data.high, limit)
+ low <- transformList(a, data.low, limit)
+ high <- transformList(a, data.high, limit)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
typeName = typeName,
id = id,
@@ -848,7 +782,7 @@ object ExpandTemplates extends AstTransformer
for {
id <- exprNodeOpt(a, data.id)
(_, group) <- matchExprNode(a, data.group)
- (_, members) <- transformList(a, data.members, tlmPacketMember)
+ members <- transformList(a, data.members, tlmPacketMember)
} yield (((), cloneAnnotatedNode(a, aNode, data.copy(
id = id,
group = group,
@@ -885,8 +819,8 @@ object ExpandTemplates extends AstTransformer
)))
for {
- (_, members) <- transformList(a, data.members, matchTlmPacketSetMember)
- (_, omitted) <- transformList(a, data.omitted, tlmChannelIdentifier)
+ members <- transformList(a, data.members, matchTlmPacketSetMember)
+ omitted <- transformList(a, data.omitted, tlmChannelIdentifier)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
members = members.flatten,
omitted = omitted
@@ -934,11 +868,9 @@ object ExpandTemplates extends AstTransformer
a <- Right(a.copy(templateDefId = None))
}
yield {
- val (_, params1) = params
- val (_, members1) = members
((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params1,
- members = members1.flatten
+ params = params,
+ members = members.flatten
)))
}
@@ -950,8 +882,7 @@ object ExpandTemplates extends AstTransformer
val data = node.data
for { result <- transformList(a, data.members, matchModuleMember) }
yield {
- val (_, members1) = result
- ((), cloneAnnotatedNode(a, aNode, data.copy(members = members1.flatten)))
+ ((), cloneAnnotatedNode(a, aNode, data.copy(members = result.flatten)))
}
}
@@ -998,6 +929,29 @@ object ExpandTemplates extends AstTransformer
(pre, cloneNode(a, node, data), post)
}
+ private def cloneQualIdentNode(
+ a: In,
+ node: AstNode[Ast.QualIdent]
+ ): AstNode[Ast.QualIdent] = {
+ node.data match {
+ case Ast.QualIdent.Qualified(qualifier, name) =>
+ cloneNode(a, node, Ast.QualIdent.Qualified(
+ cloneQualIdentNode(a, qualifier),
+ cloneNode(a, name, name.data)
+ ))
+ case Ast.QualIdent.Unqualified(name, isAbsolute) =>
+ cloneNode(a, node, Ast.QualIdent.Unqualified(name, isAbsolute))
+ }
+ }
+ private def cloneStringNodeOpt(
+ a: In,
+ node: Option[AstNode[String]]
+ ): Option[AstNode[String]] =
+ node match {
+ case None => None
+ case Some(value) => Some(cloneNode(a, value, value.data))
+ }
+
private def defaultNodeOpt[T](
a: Analysis,
node: Option[AstNode[T]]
@@ -1009,6 +963,16 @@ object ExpandTemplates extends AstTransformer
yield Some(node)
}
+ private def defEnumConstantAnnotatedNode(
+ a: In,
+ aNode: Ast.Annotated[AstNode[Ast.DefEnumConstant]]
+ ): ResultAnnotatedNode[Ast.DefEnumConstant] =
+ val data = aNode._2.data
+ for (value <- exprNodeOpt(a, data.value))
+ yield {
+ ((), cloneAnnotatedNode(a, aNode, data.copy(value = value)))
+ }
+
/** Expand a template */
private def expandTemplate(
a: Analysis,
@@ -1022,7 +986,7 @@ object ExpandTemplates extends AstTransformer
// Clone the template body, recording the expansion node so that
// cloned nodes point back at the expansion site.
// Record the template definition too for diagnostics.
- (_, members) <- transformList(
+ members <- transformList(
a.copy(
templateExpansionId = Some(node.id),
templateDefId = Some(tmpl.node._2.id)
@@ -1058,7 +1022,20 @@ object ExpandTemplates extends AstTransformer
private def formalParamList(
a: In,
aNode: Ast.FormalParamList
- ) = for ((_, node) <- transformList(a, aNode, formalAnnotatatedParam)) yield node
+ ) = for (node <- transformList(a, aNode, formalAnnotatatedParam)) yield node
+
+ private def portInstanceIdentifierNode(
+ a: In,
+ pii: AstNode[Ast.PortInstanceIdentifier]
+ ): Result.Result[AstNode[Ast.PortInstanceIdentifier]] = {
+ for {
+ interfaceInstance <- qualIdentNode(a, pii.data.interfaceInstance)
+ (_, portName) <- defaultNode(a, pii.data.portName)
+ } yield cloneNode(a, pii, pii.data.copy(
+ interfaceInstance = interfaceInstance,
+ portName = portName
+ ))
+ }
private def qualIdentNode(
a: In,
@@ -1082,6 +1059,20 @@ object ExpandTemplates extends AstTransformer
private def resultAdapter[A,B](f: (A, B) => Result.Result[B]) =
(a: A, b: B) => for (c <- f(a, b)) yield ((), c)
+ private def structMember(
+ a: Analysis,
+ node: AstNode[Ast.StructMember]
+ ) = {
+ for (result <- matchExprNode(a, node.data.value))
+ yield {
+ val (_, value) = result
+ ((), cloneNode(a, node, Ast.StructMember(
+ node.data.name,
+ value
+ )))
+ }
+ }
+
private def structTypeMemberAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.StructTypeMember]]
@@ -1103,7 +1094,7 @@ object ExpandTemplates extends AstTransformer
node: AstNode[Ast.TransitionExpr]
): Result.Result[AstNode[Ast.TransitionExpr]] =
for {
- (_, actions) <- transformList(a, node.data.actions, defaultNode)
+ actions <- transformList(a, node.data.actions, defaultNode)
target <- qualIdentNode(a, node.data.target)
} yield cloneNode(a, node, node.data.copy(
actions = actions,
@@ -1119,7 +1110,7 @@ object ExpandTemplates extends AstTransformer
for (result <- transitionExpr(a, transition))
yield Ast.TransitionOrDo.Transition(result)
case Ast.TransitionOrDo.Do(actions) =>
- for ((_, result) <- transformList(a, actions, defaultNode))
+ for (result <- transformList(a, actions, defaultNode))
yield Ast.TransitionOrDo.Do(result)
private def typeNameNodeOpt(
From d313f138c7074f502531130c71ee31771323e3b8 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 23:27:02 -0700
Subject: [PATCH 15/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 269 +++++++++---------
1 file changed, 139 insertions(+), 130 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index bb24268c0..f3c30b560 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -38,7 +38,7 @@ object ExpandTemplates extends AstTransformer
override def transUnit(
a: Analysis,
tu: Ast.TransUnit
- ): Result[Ast.TransUnit] = {
+ ) = {
for {
members <- transformList(a, tu.members, matchModuleMember)
} yield ((), Ast.TransUnit(members.flatten))
@@ -78,91 +78,104 @@ object ExpandTemplates extends AstTransformer
}
}
- override def exprArrayNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprArray): ResultNode[Ast.Expr] =
+ override def exprArrayNode(
+ a: In,
+ node: AstNode[Ast.Expr],
+ e: Ast.ExprArray
+ ) =
for { result <- transformList(a, e.elts, matchExprNode) }
- yield {
- ((), cloneNode(a, node, Ast.ExprArray(result)))
- }
+ yield ((), cloneNode(a, node, Ast.ExprArray(result)))
- override def exprArraySubscriptNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprArraySubscript): ResultNode[Ast.Expr] =
+ override def exprArraySubscriptNode(
+ a: In,
+ node: AstNode[Ast.Expr],
+ e: Ast.ExprArraySubscript
+ ) =
for {
- e1 <- matchExprNode(a, e.e1)
- e2 <- matchExprNode(a, e.e2)
- }
- yield {
- val (_, e1_) = e1
- val (_, e2_) = e2
- ((), cloneNode(a, node, Ast.ExprArraySubscript(e1_, e2_)))
+ (_, e1) <- matchExprNode(a, e.e1)
+ (_, e2) <- matchExprNode(a, e.e2)
}
+ yield ((), cloneNode(a, node, Ast.ExprArraySubscript(e1, e2)))
- override def exprBinopNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprBinop): ResultNode[Ast.Expr] =
+ override def exprBinopNode(
+ a: In, node: AstNode[Ast.Expr],
+ e: Ast.ExprBinop
+ ) =
for {
- e1 <- matchExprNode(a, e.e1)
- e2 <- matchExprNode(a, e.e2)
- }
- yield {
- val (_, e1_) = e1
- val (_, e2_) = e2
- ((), cloneNode(a, node, Ast.ExprBinop(e1_, e.op, e2_)))
+ (_, e1) <- matchExprNode(a, e.e1)
+ (_, e2) <- matchExprNode(a, e.e2)
}
+ yield ((), cloneNode(a, node, Ast.ExprBinop(e1, e.op, e2)))
- override def exprDotNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprDot): ResultNode[Ast.Expr] =
- for (result <- matchExprNode(a, e.e))
- yield {
- val (_, left) = result
- ((), cloneNode(a, node, Ast.ExprDot(left, cloneNode(a, e.id, e.id.data))))
- }
+ override def exprDotNode(
+ a: In,
+ node: AstNode[Ast.Expr],
+ e: Ast.ExprDot
+ ) =
+ for ((_, left) <- matchExprNode(a, e.e))
+ yield ((), cloneNode(a, node, Ast.ExprDot(left, cloneNode(a, e.id, e.id.data))))
- override def exprParenNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprParen): ResultNode[Ast.Expr] =
- for (result <- matchExprNode(a, e.e))
- yield {
- val (_, value) = result
- ((), cloneNode(a, node, Ast.ExprParen(value)))
- }
+ override def exprParenNode(
+ a: In,
+ node: AstNode[Ast.Expr],
+ e: Ast.ExprParen
+ ) =
+ for ((_, value) <- matchExprNode(a, e.e))
+ yield ((), cloneNode(a, node, Ast.ExprParen(value)))
override def exprStructNode(
a: Analysis,
node: AstNode[Ast.Expr],
e: Ast.ExprStruct
) =
- for { result <- transformList(a, e.members, structMember) }
- yield {
- ((), cloneNode(a, node, Ast.ExprStruct(result)))
- }
+ for (result <- transformList(a, e.members, resultAdapter(structMember)))
+ yield ((), cloneNode(a, node, Ast.ExprStruct(result)))
- override def exprUnopNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprUnop) =
+ override def exprUnopNode(
+ a: In,
+ node: AstNode[Ast.Expr],
+ e: Ast.ExprUnop
+ ) =
for ((_, ec) <- matchExprNode(a, e.e))
- yield ((), cloneNode(a, node, Ast.ExprUnop(e.op, ec)))
+ yield ((), cloneNode(a, node, Ast.ExprUnop(e.op, ec)))
- override def exprSizeOfNode(a: In, node: AstNode[Ast.Expr], e: Ast.ExprSizeOf): ResultNode[Ast.Expr] =
+ override def exprSizeOfNode(
+ a: In,
+ node: AstNode[Ast.Expr],
+ e: Ast.ExprSizeOf
+ ) =
for ((_, result) <- matchTypeName(a, e.typeName))
- yield ((), cloneNode(a, node, Ast.ExprSizeOf(result)))
+ yield ((), cloneNode(a, node, Ast.ExprSizeOf(result)))
override def typeNameQualIdentNode(
a: In,
node: AstNode[Ast.TypeName],
tn: Ast.TypeNameQualIdent
- ): ResultNode[Ast.TypeName] = {
- Right(((), cloneNode(a, node, Ast.TypeNameQualIdent(
- cloneQualIdentNode(a, tn.name)
- ))))
- }
+ ): ResultNode[Ast.TypeName] =
+ Right(
+ (),
+ cloneNode(a, node, Ast.TypeNameQualIdent(cloneQualIdentNode(a, tn.name)))
+ )
override def typeNameStringNode(
a: In,
node: AstNode[Ast.TypeName],
tn: Ast.TypeNameString
): ResultNode[Ast.TypeName] = {
- tn.size match {
- case None =>
- Right(((), cloneNode(a, node, Ast.TypeNameString(None))))
- case Some(size) =>
- for (result <- matchExprNode(a, size))
- yield {
- val (_, value) = result
- ((), cloneNode(a, node, Ast.TypeNameString(Some(value))))
- }
+// tn.size match {
+// case None =>
+// Right(((), cloneNode(a, node, Ast.TypeNameString(None))))
+// case Some(size) =>
+// for ((_, value) <- matchExprNode(a, size))
+// yield ((), cloneNode(a, node, Ast.TypeNameString(Some(value))))
+// }
+ for {
+ valueOpt <- tn.size match {
+ case None => Right(None)
+ case Some(size) => matchExprNode(a, size).map(_._2).map(Some(_))
+ }
}
+ yield ((), cloneNode(a, node, Ast.TypeNameString(valueOpt)))
}
override def defAliasTypeAnnotatedNode(
@@ -170,46 +183,48 @@ object ExpandTemplates extends AstTransformer
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
): ResultAnnotatedNode[Ast.DefAliasType] =
val data = aNode._2.data
- for (result <- matchTypeName(a, data.typeName))
- yield {
- val (_, ty) = result
- ((), cloneAnnotatedNode(
- a, aNode, data.copy(typeName = ty)
- ))
- }
+ for ((_, ty) <- matchTypeName(a, data.typeName))
+ yield (
+ (),
+ cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
+ )
- override def defArrayAnnotatedNode(a: In, aNode: Ast.Annotated[AstNode[Ast.DefArray]]): ResultAnnotatedNode[Ast.DefArray] =
+ override def defArrayAnnotatedNode(
+ a: In,
+ aNode: Ast.Annotated[AstNode[Ast.DefArray]]
+ ) = {
val data = aNode._2.data
for {
(_, size) <- matchExprNode(a, data.size)
(_, eltType) <- matchTypeName(a, data.eltType)
default <- exprNodeOpt(a, data.default)
- } yield {
- (
- (),
- cloneAnnotatedNode(
- a, aNode,
- data.copy(
- size = size,
- eltType = eltType,
- default = default,
- format = cloneStringNodeOpt(a, data.format)
- )
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a, aNode,
+ data.copy(
+ size = size,
+ eltType = eltType,
+ default = default,
+ format = cloneStringNodeOpt(a, data.format)
)
)
- }
+ )
+ }
- override def defComponentAnnotatedNode(a: In, aNode: Ast.Annotated[AstNode[Ast.DefComponent]]): ResultAnnotatedNode[Ast.DefComponent] =
+ override def defComponentAnnotatedNode(
+ a: In,
+ aNode: Ast.Annotated[AstNode[Ast.DefComponent]]
+ ) = {
val data = aNode._2.data
for (result <- transformList(a, data.members, matchComponentMember))
- yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(members = result.flatten)))
- }
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = result.flatten)))
+ }
override def defComponentInstanceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefComponentInstance]]
- ): ResultAnnotatedNode[Ast.DefComponentInstance] =
+ ): ResultAnnotatedNode[Ast.DefComponentInstance] = {
val data = aNode._2.data
for {
component <- Right(cloneQualIdentNode(a, data.component))
@@ -219,32 +234,33 @@ object ExpandTemplates extends AstTransformer
priority <- exprNodeOpt(a, data.priority)
cpu <- exprNodeOpt(a, data.cpu)
initSpecs <- transformList(a, data.initSpecs, specInitAnnotatedNode)
- } yield {
- (
- (),
- cloneAnnotatedNode(
- a, aNode,
- data.copy(
- component=component,
- baseId=baseId,
- implType=cloneStringNodeOpt(a, data.implType),
- file=cloneStringNodeOpt(a, data.file),
- queueSize=queueSize,
- stackSize=stackSize,
- priority=priority,
- cpu=cpu,
- initSpecs=initSpecs
- )
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a, aNode,
+ data.copy(
+ component=component,
+ baseId=baseId,
+ implType=cloneStringNodeOpt(a, data.implType),
+ file=cloneStringNodeOpt(a, data.file),
+ queueSize=queueSize,
+ stackSize=stackSize,
+ priority=priority,
+ cpu=cpu,
+ initSpecs=initSpecs
)
)
- }
+ )
+ }
- override def defInterfaceAnnotatedNode(a: In, aNode: Ast.Annotated[AstNode[Ast.DefInterface]]): ResultAnnotatedNode[Ast.DefInterface] =
+ override def defInterfaceAnnotatedNode(
+ a: In,
+ aNode: Ast.Annotated[AstNode[Ast.DefInterface]]
+ ) = {
val data = aNode._2.data
for (result <- transformList(a, data.members, matchInterfaceMember))
- yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(members=result)))
- }
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members=result)))
+ }
override def defConstantAnnotatedNode(
a: In,
@@ -266,7 +282,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
typeName <- typeNameNodeOpt(a, data.typeName)
- constants <- transformList(a, data.constants, defEnumConstantAnnotatedNode)
+ constants <- transformList(a, data.constants, resultAdapter(defEnumConstantAnnotatedNode))
default <- exprNodeOpt(a, data.default)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
typeName = typeName,
@@ -377,9 +393,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
transition <- transitionExpr(a, data.transition)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(transition = transition)))
- }
+ } yield ((), cloneAnnotatedNode(a, aNode, data.copy(transition = transition)))
override def specStateEntryAnnotatedNode(
a: In,
@@ -388,9 +402,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
actions <- transformList(a, data.actions, defaultNode)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
- }
+ } yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
override def specStateExitAnnotatedNode(
a: In,
@@ -399,9 +411,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
actions <- transformList(a, data.actions, defaultNode)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
- }
+ } yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
override def specStateTransitionAnnotatedNode(
a: In,
@@ -426,7 +436,7 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefStruct] =
val data = aNode._2.data
for {
- members <- transformList(a, data.members, structTypeMemberAnnotatedNode)
+ members <- transformList(a, data.members, resultAdapter(structTypeMemberAnnotatedNode))
default <- exprNodeOpt(a, data.default)
} yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
@@ -589,7 +599,7 @@ object ExpandTemplates extends AstTransformer
override def specIncludeAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecInclude]]
- ): ResultAnnotatedNode[Ast.SpecInclude] =
+ ) =
val data = aNode._2.data
for {
(_, file) <- defaultNode(a, data.file)
@@ -598,7 +608,7 @@ object ExpandTemplates extends AstTransformer
override def specInitAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecInit]]
- ): ResultAnnotatedNode[Ast.SpecInit] =
+ ) =
val data = aNode._2.data
for (result <- matchExprNode(a, data.phase))
yield {
@@ -896,7 +906,7 @@ object ExpandTemplates extends AstTransformer
// Members are already there; nothing to do
case Some(members) => Right((), aNode)
// Members are not there; expand
- case None => expandTemplate(a, aNode)
+ case None => (resultAdapter(expandTemplate))(a, aNode)
}
}
@@ -943,6 +953,7 @@ object ExpandTemplates extends AstTransformer
cloneNode(a, node, Ast.QualIdent.Unqualified(name, isAbsolute))
}
}
+
private def cloneStringNodeOpt(
a: In,
node: Option[AstNode[String]]
@@ -966,18 +977,16 @@ object ExpandTemplates extends AstTransformer
private def defEnumConstantAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefEnumConstant]]
- ): ResultAnnotatedNode[Ast.DefEnumConstant] =
+ ): Result.Result[Ast.Annotated[AstNode[Ast.DefEnumConstant]]] =
val data = aNode._2.data
for (value <- exprNodeOpt(a, data.value))
- yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(value = value)))
- }
+ yield cloneAnnotatedNode(a, aNode, data.copy(value = value))
/** Expand a template */
private def expandTemplate(
a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
- ): ResultAnnotatedNode[Ast.SpecTemplateExpand] = {
+ ): Result.Result[Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]] = {
val (pre, node, post) = aNode
val data = node.data
for {
@@ -996,7 +1005,7 @@ object ExpandTemplates extends AstTransformer
)
} yield {
// Paste the expanded template body into the expansion specifier
- ((), (pre, AstNode.create(data.copy(members = Some(members.flatten)), node.id), post))
+ (pre, AstNode.create(data.copy(members = Some(members.flatten)), node.id), post)
}
}
@@ -1017,12 +1026,13 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for ((_, ty) <- matchTypeName(a, data.typeName))
- yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = ty)))
+ yield cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
private def formalParamList(
a: In,
aNode: Ast.FormalParamList
- ) = for (node <- transformList(a, aNode, formalAnnotatatedParam)) yield node
+ ) = for (node <- transformList(a, aNode, resultAdapter(formalAnnotatatedParam)))
+ yield node
private def portInstanceIdentifierNode(
a: In,
@@ -1063,13 +1073,12 @@ object ExpandTemplates extends AstTransformer
a: Analysis,
node: AstNode[Ast.StructMember]
) = {
- for (result <- matchExprNode(a, node.data.value))
+ for ((_, value) <- matchExprNode(a, node.data.value))
yield {
- val (_, value) = result
- ((), cloneNode(a, node, Ast.StructMember(
+ cloneNode(a, node, Ast.StructMember(
node.data.name,
value
- )))
+ ))
}
}
@@ -1082,11 +1091,11 @@ object ExpandTemplates extends AstTransformer
size <- exprNodeOpt(a, data.size)
(_, typeName) <- matchTypeName(a, data.typeName)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
+ cloneAnnotatedNode(a, aNode, data.copy(
size = size,
typeName = typeName,
format = cloneStringNodeOpt(a, data.format)
- )))
+ ))
}
private def transitionExpr(
@@ -1098,7 +1107,7 @@ object ExpandTemplates extends AstTransformer
target <- qualIdentNode(a, node.data.target)
} yield cloneNode(a, node, node.data.copy(
actions = actions,
- target = target,
+ target = target
))
private def transitionOrDo(
From bce7e7a498c53c0bbb00f68c3c3bb7d94d01d084 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 23:50:16 -0700
Subject: [PATCH 16/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 209 +++++++++---------
1 file changed, 104 insertions(+), 105 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index f3c30b560..e5dc9cc54 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -35,13 +35,19 @@ object ExpandTemplates extends AstTransformer
helper(list, Nil).map(_.reverse)
}
+ /** Transform a list and flatten the result */
+ def transformFlatList[A, B](
+ s: State,
+ list: List[A],
+ transform: (State, A) => Result[List[B]]
+ ): Result.Result[List[B]] = transformList(s, list, transform).map(_.flatten)
+
override def transUnit(
a: Analysis,
tu: Ast.TransUnit
) = {
- for {
- members <- transformList(a, tu.members, matchModuleMember)
- } yield ((), Ast.TransUnit(members.flatten))
+ for (members <- transformFlatList(a, tu.members, matchModuleMember))
+ yield ((), Ast.TransUnit(members))
}
// Duplicate every node inside a template definition
@@ -151,7 +157,7 @@ object ExpandTemplates extends AstTransformer
a: In,
node: AstNode[Ast.TypeName],
tn: Ast.TypeNameQualIdent
- ): ResultNode[Ast.TypeName] =
+ ) =
Right(
(),
cloneNode(a, node, Ast.TypeNameQualIdent(cloneQualIdentNode(a, tn.name)))
@@ -161,14 +167,7 @@ object ExpandTemplates extends AstTransformer
a: In,
node: AstNode[Ast.TypeName],
tn: Ast.TypeNameString
- ): ResultNode[Ast.TypeName] = {
-// tn.size match {
-// case None =>
-// Right(((), cloneNode(a, node, Ast.TypeNameString(None))))
-// case Some(size) =>
-// for ((_, value) <- matchExprNode(a, size))
-// yield ((), cloneNode(a, node, Ast.TypeNameString(Some(value))))
-// }
+ ) =
for {
valueOpt <- tn.size match {
case None => Right(None)
@@ -176,7 +175,6 @@ object ExpandTemplates extends AstTransformer
}
}
yield ((), cloneNode(a, node, Ast.TypeNameString(valueOpt)))
- }
override def defAliasTypeAnnotatedNode(
a: In,
@@ -217,14 +215,14 @@ object ExpandTemplates extends AstTransformer
aNode: Ast.Annotated[AstNode[Ast.DefComponent]]
) = {
val data = aNode._2.data
- for (result <- transformList(a, data.members, matchComponentMember))
- yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = result.flatten)))
+ for (members <- transformFlatList(a, data.members, matchComponentMember))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = members)))
}
override def defComponentInstanceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefComponentInstance]]
- ): ResultAnnotatedNode[Ast.DefComponentInstance] = {
+ ) = {
val data = aNode._2.data
for {
component <- Right(cloneQualIdentNode(a, data.component))
@@ -265,7 +263,7 @@ object ExpandTemplates extends AstTransformer
override def defConstantAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefConstant]]
- ): ResultAnnotatedNode[Ast.DefConstant] =
+ ) =
val data = aNode._2.data
for ((_, value) <- matchExprNode(a, data.value))
yield {
@@ -278,11 +276,15 @@ object ExpandTemplates extends AstTransformer
override def defEnumAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefEnum]]
- ): ResultAnnotatedNode[Ast.DefEnum] =
+ ) =
val data = aNode._2.data
for {
typeName <- typeNameNodeOpt(a, data.typeName)
- constants <- transformList(a, data.constants, resultAdapter(defEnumConstantAnnotatedNode))
+ constants <- transformList(
+ a,
+ data.constants,
+ resultAdapter(defEnumConstantAnnotatedNode)
+ )
default <- exprNodeOpt(a, data.default)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
typeName = typeName,
@@ -293,7 +295,7 @@ object ExpandTemplates extends AstTransformer
override def defPortAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefPort]]
- ): ResultAnnotatedNode[Ast.DefPort] =
+ ) =
val data = aNode._2.data
for {
params <- formalParamList(a, data.params)
@@ -306,22 +308,22 @@ object ExpandTemplates extends AstTransformer
override def defStateMachineAnnotatedNodeExternal(
in: In,
node: Ast.Annotated[AstNode[Ast.DefStateMachine]]
- ): ResultAnnotatedNode[Ast.DefStateMachine] =
+ ) =
defaultAnnotatedNode(in, node)
override def defStateMachineAnnotatedNodeInternal(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefStateMachine]],
members: List[Ast.StateMachineMember]
- ): ResultAnnotatedNode[Ast.DefStateMachine] =
+ ) =
val data = aNode._2.data
- for (result <- transformList(a, members, matchStateMachineMember))
- yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = Some(result.flatten))))
+ for (members <- transformFlatList(a, members, matchStateMachineMember))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = Some(members))))
override def defStateMachineAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefStateMachine]]
- ): ResultAnnotatedNode[Ast.DefStateMachine] =
+ ) =
val data = aNode._2.data
data.members match {
case None => defStateMachineAnnotatedNodeExternal(a, aNode)
@@ -331,7 +333,7 @@ object ExpandTemplates extends AstTransformer
override def defActionAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefAction]]
- ): ResultAnnotatedNode[Ast.DefAction] =
+ ) =
val data = aNode._2.data
for {
typeName <- typeNameNodeOpt(a, data.typeName)
@@ -342,7 +344,7 @@ object ExpandTemplates extends AstTransformer
override def defChoiceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefChoice]]
- ): ResultAnnotatedNode[Ast.DefChoice] =
+ ) =
val data = aNode._2.data
for {
(_, guard) <- defaultNode(a, data.guard)
@@ -359,64 +361,55 @@ object ExpandTemplates extends AstTransformer
override def defGuardAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefGuard]]
- ): ResultAnnotatedNode[Ast.DefGuard] =
+ ) =
val data = aNode._2.data
- for {
- typeName <- typeNameNodeOpt(a, data.typeName)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
- }
+ for (typeName <- typeNameNodeOpt(a, data.typeName))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
override def defSignalAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefSignal]]
- ): ResultAnnotatedNode[Ast.DefSignal] =
+ ) =
val data = aNode._2.data
- for {
- typeName <- typeNameNodeOpt(a, data.typeName)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
- }
+ for (typeName <- typeNameNodeOpt(a, data.typeName))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
override def defStateAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefState]]
- ): ResultAnnotatedNode[Ast.DefState] =
+ ) =
val data = aNode._2.data
- for (members <- transformList(a, data.members, matchStateMember))
- yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = members.flatten)))
+ for (members <- transformFlatList(a, data.members, matchStateMember))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = members)))
override def specInitialTransitionAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecInitialTransition]]
- ): ResultAnnotatedNode[Ast.SpecInitialTransition] =
+ ) =
val data = aNode._2.data
- for {
- transition <- transitionExpr(a, data.transition)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(transition = transition)))
+ for (transition <- transitionExpr(a, data.transition))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(transition = transition)))
override def specStateEntryAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecStateEntry]]
- ): ResultAnnotatedNode[Ast.SpecStateEntry] =
+ ) =
val data = aNode._2.data
- for {
- actions <- transformList(a, data.actions, defaultNode)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
+ for (actions <- transformList(a, data.actions, defaultNode))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
override def specStateExitAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecStateExit]]
- ): ResultAnnotatedNode[Ast.SpecStateExit] =
+ ) =
val data = aNode._2.data
- for {
- actions <- transformList(a, data.actions, defaultNode)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
+ for (actions <- transformList(a, data.actions, defaultNode))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
override def specStateTransitionAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecStateTransition]]
- ): ResultAnnotatedNode[Ast.SpecStateTransition] =
+ ) =
val data = aNode._2.data
for {
(_, signal) <- defaultNode(a, data.signal)
@@ -433,7 +426,7 @@ object ExpandTemplates extends AstTransformer
override def defStructAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefStruct]]
- ): ResultAnnotatedNode[Ast.DefStruct] =
+ ) =
val data = aNode._2.data
for {
members <- transformList(a, data.members, resultAdapter(structTypeMemberAnnotatedNode))
@@ -448,35 +441,39 @@ object ExpandTemplates extends AstTransformer
override def defTopologyAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefTopology]]
- ): ResultAnnotatedNode[Ast.DefTopology] =
+ ) =
val data = aNode._2.data
for {
- members <- transformList(a, data.members, matchTopologyMember)
+ members <- transformFlatList(a, data.members, matchTopologyMember)
implements <- transformList(a, data.implements, (a, q) => Right(((), cloneQualIdentNode(a, q))))
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- members = members.flatten,
- implements = implements
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(members = members, implements = implements)
+ )
+ )
override def defSystemAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefSystem]]
- ): ResultAnnotatedNode[Ast.DefSystem] =
+ ) =
val data = aNode._2.data
- for {
- topology <- qualIdentNode(a, data.topology)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- topology = topology
- )))
- }
+ for (topology <- qualIdentNode(a, data.topology))
+ yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(topology = topology)
+ )
+ )
override def specCommandAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecCommand]]
- ): ResultAnnotatedNode[Ast.SpecCommand] =
+ ) =
val data = aNode._2.data
for {
params <- formalParamList(a, data.params)
@@ -495,7 +492,7 @@ object ExpandTemplates extends AstTransformer
override def specInstanceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecInstance]]
- ): ResultAnnotatedNode[Ast.SpecInstance] =
+ ) =
val data = aNode._2.data
for {
instance <- qualIdentNode(a, data.instance)
@@ -508,7 +505,7 @@ object ExpandTemplates extends AstTransformer
override def specConnectionGraphAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecConnectionGraph]]
- ): ResultAnnotatedNode[Ast.SpecConnectionGraph] =
+ ) =
val data = aNode._2.data
def connection(
@@ -551,7 +548,7 @@ object ExpandTemplates extends AstTransformer
override def specContainerAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecContainer]]
- ): ResultAnnotatedNode[Ast.SpecContainer] =
+ ) =
val data = aNode._2.data
for {
id <- exprNodeOpt(a, data.id)
@@ -566,7 +563,7 @@ object ExpandTemplates extends AstTransformer
override def specEventAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecEvent]]
- ): ResultAnnotatedNode[Ast.SpecEvent] =
+ ) =
val data = aNode._2.data
for {
params <- formalParamList(a, data.params)
@@ -619,7 +616,7 @@ object ExpandTemplates extends AstTransformer
override def specInternalPortAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecInternalPort]]
- ): ResultAnnotatedNode[Ast.SpecInternalPort] =
+ ) =
val data = aNode._2.data
for {
params <- formalParamList(a, data.params)
@@ -632,7 +629,7 @@ object ExpandTemplates extends AstTransformer
override def specLocAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecLoc]]
- ): ResultAnnotatedNode[Ast.SpecLoc] =
+ ) =
val data = aNode._2.data
for {
symbol <- qualIdentNode(a, data.symbol)
@@ -645,7 +642,7 @@ object ExpandTemplates extends AstTransformer
override def specParamAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecParam]]
- ): ResultAnnotatedNode[Ast.SpecParam] =
+ ) =
val data = aNode._2.data
for {
(_, typeName) <- matchTypeName(a, data.typeName)
@@ -664,7 +661,7 @@ object ExpandTemplates extends AstTransformer
override def specPortInstanceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecPortInstance]]
- ): ResultAnnotatedNode[Ast.SpecPortInstance] =
+ ) =
val data = aNode._2.data
data match {
case data @ Ast.SpecPortInstance.General(_, _, _, _, _, _) =>
@@ -696,7 +693,7 @@ object ExpandTemplates extends AstTransformer
override def specPortMatchingAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecPortMatching]]
- ): ResultAnnotatedNode[Ast.SpecPortMatching] =
+ ) =
val data = aNode._2.data
for {
(_, port1) <- defaultNode(a, data.port1)
@@ -709,7 +706,7 @@ object ExpandTemplates extends AstTransformer
override def specRecordAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecRecord]]
- ): ResultAnnotatedNode[Ast.SpecRecord] =
+ ) =
val data = aNode._2.data
for {
(_, recordType) <- matchTypeName(a, data.recordType)
@@ -722,7 +719,7 @@ object ExpandTemplates extends AstTransformer
override def specStateMachineInstanceAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecStateMachineInstance]]
- ): ResultAnnotatedNode[Ast.SpecStateMachineInstance] =
+ ) =
val data = aNode._2.data
for {
stateMachine <- qualIdentNode(a, data.stateMachine)
@@ -735,7 +732,7 @@ object ExpandTemplates extends AstTransformer
override def specTlmChannelAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecTlmChannel]]
- ): ResultAnnotatedNode[Ast.SpecTlmChannel] =
+ ) =
val data = aNode._2.data
def limit(
a: In,
@@ -764,7 +761,7 @@ object ExpandTemplates extends AstTransformer
override def specTlmPacketAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecTlmPacket]]
- ): ResultAnnotatedNode[Ast.SpecTlmPacket] =
+ ) =
val data = aNode._2.data
def tlmPacketMember(
a: In,
@@ -802,18 +799,22 @@ object ExpandTemplates extends AstTransformer
override def specTopPortAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecTopPort]]
- ): ResultAnnotatedNode[Ast.SpecTopPort] =
+ ) =
val data = aNode._2.data
- for {
- underlyingPort <- portInstanceIdentifierNode(a, data.underlyingPort)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- underlyingPort = underlyingPort
- )))
+ for (underlyingPort <- portInstanceIdentifierNode(a, data.underlyingPort))
+ yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(underlyingPort = underlyingPort)
+ )
+ )
override def specTlmPacketSetAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecTlmPacketSet]]
- ): ResultAnnotatedNode[Ast.SpecTlmPacketSet] =
+ ) =
val data = aNode._2.data
def tlmChannelIdentifier(
a: In,
@@ -829,17 +830,17 @@ object ExpandTemplates extends AstTransformer
)))
for {
- members <- transformList(a, data.members, matchTlmPacketSetMember)
+ members <- transformFlatList(a, data.members, matchTlmPacketSetMember)
omitted <- transformList(a, data.omitted, tlmChannelIdentifier)
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- members = members.flatten,
+ members = members,
omitted = omitted
)))
override def specInterfaceImportAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecImport]]
- ): ResultAnnotatedNode[Ast.SpecImport] =
+ ) =
val data = aNode._2.data
for {
sym <- qualIdentNode(a, data.sym)
@@ -850,7 +851,7 @@ object ExpandTemplates extends AstTransformer
override def defModuleTemplateAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.DefModuleTemplate]]
- ): ResultAnnotatedNode[Ast.DefModuleTemplate] =
+ ) =
val (_, node, _) = aNode
val data = node.data
@@ -874,13 +875,13 @@ object ExpandTemplates extends AstTransformer
for {
a <- Right(a.copy(templateDefId = Some(node.id)))
params <- transformList(a, data.params, templateParam)
- members <- transformList(a, data.members, matchModuleMember)
+ members <- transformFlatList(a, data.members, matchModuleMember)
a <- Right(a.copy(templateDefId = None))
}
yield {
((), cloneAnnotatedNode(a, aNode, data.copy(
params = params,
- members = members.flatten
+ members = members
)))
}
@@ -890,10 +891,8 @@ object ExpandTemplates extends AstTransformer
) = {
val (_, node, _) = aNode
val data = node.data
- for { result <- transformList(a, data.members, matchModuleMember) }
- yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(members = result.flatten)))
- }
+ for (members <- transformFlatList(a, data.members, matchModuleMember))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = members)))
}
override def specTemplateExpandAnnotatedNode(
@@ -995,7 +994,7 @@ object ExpandTemplates extends AstTransformer
// Clone the template body, recording the expansion node so that
// cloned nodes point back at the expansion site.
// Record the template definition too for diagnostics.
- members <- transformList(
+ members <- transformFlatList(
a.copy(
templateExpansionId = Some(node.id),
templateDefId = Some(tmpl.node._2.id)
@@ -1005,7 +1004,7 @@ object ExpandTemplates extends AstTransformer
)
} yield {
// Paste the expanded template body into the expansion specifier
- (pre, AstNode.create(data.copy(members = Some(members.flatten)), node.id), post)
+ (pre, AstNode.create(data.copy(members = Some(members)), node.id), post)
}
}
From 84f9d3c76f934833b3c02ebd95cf6abd95040bc2 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Mon, 12 Oct 2026 23:59:18 -0700
Subject: [PATCH 17/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 31 +++++++++++++------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index e5dc9cc54..04fa2eb28 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -860,16 +860,27 @@ object ExpandTemplates extends AstTransformer
param: Ast.Annotated[AstNode[Ast.TemplateParam]]
): ResultAnnotatedNode[Ast.TemplateParam] = {
val (_, node, _) = param
- node.data match {
- case data @ Ast.TemplateParam.Constant(_, tn) =>
- for ((_, tn) <- matchTypeName(a, tn))
- yield ((), cloneAnnotatedNode(a, param, data.copy(typeName = tn)))
- case data @ Ast.TemplateParam.Type(_) =>
- Right(((), cloneAnnotatedNode(a, param, data)))
- case data @ Ast.TemplateParam.Interface(_, interface) =>
- for (interface <- qualIdentNode(a, interface))
- yield ((), cloneAnnotatedNode(a, param, data.copy(interface = interface)))
- }
+ for {
+ data <- node.data match {
+ case data @ Ast.TemplateParam.Constant(_, tn) =>
+ for ((_, tn) <- matchTypeName(a, tn))
+ yield data.copy(typeName = tn)
+ case data @ Ast.TemplateParam.Type(_) => Right(data)
+ case data @ Ast.TemplateParam.Interface(_, interface) =>
+ for (interface <- qualIdentNode(a, interface))
+ yield data.copy(interface = interface)
+ }
+ } yield ((), cloneAnnotatedNode(a, param, data))
+// node.data match {
+// case data @ Ast.TemplateParam.Constant(_, tn) =>
+// for ((_, tn) <- matchTypeName(a, tn))
+// yield ((), cloneAnnotatedNode(a, param, data.copy(typeName = tn)))
+// case data @ Ast.TemplateParam.Type(_) =>
+// Right(((), cloneAnnotatedNode(a, param, data)))
+// case data @ Ast.TemplateParam.Interface(_, interface) =>
+// for (interface <- qualIdentNode(a, interface))
+// yield ((), cloneAnnotatedNode(a, param, data.copy(interface = interface)))
+// }
}
for {
From c11355c9e788e76c0380b8c453ab35aabaf87b1d Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 00:27:53 -0700
Subject: [PATCH 18/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 620 +++++++++++-------
1 file changed, 381 insertions(+), 239 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 04fa2eb28..cca90307a 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -60,12 +60,15 @@ object ExpandTemplates extends AstTransformer
case Some(expansionNode) => {
val out = AstNode.create(node.data)
val inLoc = Locations.get(node.id)
- Locations.put(out.id, Location(
- inLoc.file,
- inLoc.pos,
- inLoc.includingLoc,
- Some(Locations.get(expansionNode))
- ))
+ Locations.put(
+ out.id,
+ Location(
+ inLoc.file,
+ inLoc.pos,
+ inLoc.includingLoc,
+ Some(Locations.get(expansionNode))
+ )
+ )
Right((), out)
}
}
@@ -90,7 +93,7 @@ object ExpandTemplates extends AstTransformer
e: Ast.ExprArray
) =
for { result <- transformList(a, e.elts, matchExprNode) }
- yield ((), cloneNode(a, node, Ast.ExprArray(result)))
+ yield ((), cloneNode(a, node, Ast.ExprArray(result)))
override def exprArraySubscriptNode(
a: In,
@@ -182,10 +185,10 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefAliasType] =
val data = aNode._2.data
for ((_, ty) <- matchTypeName(a, data.typeName))
- yield (
- (),
- cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
- )
+ yield (
+ (),
+ cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
+ )
override def defArrayAnnotatedNode(
a: In,
@@ -266,12 +269,13 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for ((_, value) <- matchExprNode(a, data.value))
- yield {
- ((),
- cloneAnnotatedNode(
- a, aNode,
- data.copy(value = value)))
- }
+ yield (
+ (),
+ cloneAnnotatedNode(
+ a, aNode,
+ data.copy(value = value)
+ )
+ )
override def defEnumAnnotatedNode(
a: In,
@@ -286,11 +290,18 @@ object ExpandTemplates extends AstTransformer
resultAdapter(defEnumConstantAnnotatedNode)
)
default <- exprNodeOpt(a, data.default)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- typeName = typeName,
- constants = constants,
- default = default
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ typeName = typeName,
+ constants = constants,
+ default = default
+ )
+ )
+ )
override def defPortAnnotatedNode(
a: In,
@@ -300,10 +311,14 @@ object ExpandTemplates extends AstTransformer
for {
params <- formalParamList(a, data.params)
returnType <- typeNameNodeOpt(a, data.returnType)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params,
- returnType = returnType
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(params = params, returnType = returnType)
+ )
+ )
override def defStateMachineAnnotatedNodeExternal(
in: In,
@@ -350,13 +365,18 @@ object ExpandTemplates extends AstTransformer
(_, guard) <- defaultNode(a, data.guard)
ifTransition <- transitionExpr(a, data.ifTransition)
elseTransition <- transitionExpr(a, data.elseTransition)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- guard = guard,
- ifTransition = ifTransition,
- elseTransition = elseTransition
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ guard = guard,
+ ifTransition = ifTransition,
+ elseTransition = elseTransition
+ )
+ )
+ )
override def defGuardAnnotatedNode(
a: In,
@@ -415,13 +435,18 @@ object ExpandTemplates extends AstTransformer
(_, signal) <- defaultNode(a, data.signal)
guard <- defaultNodeOpt(a, data.guard)
transitionOrDo <- transitionOrDo(a, data.transitionOrDo)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- signal = signal,
- guard = guard,
- transitionOrDo = transitionOrDo
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ signal = signal,
+ guard = guard,
+ transitionOrDo = transitionOrDo
+ )
+ )
+ )
override def defStructAnnotatedNode(
a: In,
@@ -431,12 +456,14 @@ object ExpandTemplates extends AstTransformer
for {
members <- transformList(a, data.members, resultAdapter(structTypeMemberAnnotatedNode))
default <- exprNodeOpt(a, data.default)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- members = members,
- default = default
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(members = members, default = default)
+ )
+ )
override def defTopologyAnnotatedNode(
a: In,
@@ -461,14 +488,14 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for (topology <- qualIdentNode(a, data.topology))
- yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(topology = topology)
+ yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(topology = topology)
+ )
)
- )
override def specCommandAnnotatedNode(
a: In,
@@ -480,14 +507,19 @@ object ExpandTemplates extends AstTransformer
opcode <- exprNodeOpt(a, data.opcode)
priority <- exprNodeOpt(a, data.priority)
queueFull <- defaultNodeOpt(a, data.queueFull)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params,
- opcode = opcode,
- priority = priority,
- queueFull = queueFull,
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ params = params,
+ opcode = opcode,
+ priority = priority,
+ queueFull = queueFull,
+ )
+ )
+ )
override def specInstanceAnnotatedNode(
a: In,
@@ -496,11 +528,14 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
instance <- qualIdentNode(a, data.instance)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- instance = instance,
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(instance = instance)
+ )
+ )
override def specConnectionGraphAnnotatedNode(
a: In,
@@ -517,31 +552,40 @@ object ExpandTemplates extends AstTransformer
fromIndex <- exprNodeOpt(a, connection.fromIndex)
toPort <- portInstanceIdentifierNode(a, connection.toPort)
toIndex <- exprNodeOpt(a, connection.toIndex)
- } yield {
- ((), connection.copy(
+ } yield (
+ (),
+ connection.copy(
fromPort = fromPort,
fromIndex = fromIndex,
toPort = toPort,
- toIndex = toIndex,
- ))
- }
+ toIndex = toIndex
+ )
+ )
}
data match {
case data @ Ast.SpecConnectionGraph.Direct(_, connections) =>
- for {
- connections <- transformList(a, connections, connection)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- connections = connections
- )))
+ for (connections <- transformList(a, connections, connection))
+ yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(connections = connections)
+ )
+ )
case data @ Ast.SpecConnectionGraph.Pattern(_, source, targets) =>
for {
source <- qualIdentNode(a, source)
targets <- transformList(a, targets, resultAdapter(qualIdentNode))
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- source = source,
- targets = targets
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(source = source, targets = targets)
+ )
+ )
}
@@ -553,12 +597,17 @@ object ExpandTemplates extends AstTransformer
for {
id <- exprNodeOpt(a, data.id)
defaultPriority <- exprNodeOpt(a, data.defaultPriority)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- id = id,
- defaultPriority = defaultPriority,
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ id = id,
+ defaultPriority = defaultPriority
+ )
+ )
+ )
override def specEventAnnotatedNode(
a: In,
@@ -576,22 +625,31 @@ object ExpandTemplates extends AstTransformer
for {
(_, count) <- matchExprNode(a, throttle.data.count)
every <- exprNodeOpt(a, throttle.data.every)
- } yield Some(cloneNode(
- a, throttle, throttle.data.copy(
- every = every,
- count = count
+ } yield Some(
+ cloneNode(
+ a,
+ throttle,
+ throttle.data.copy(
+ every = every,
+ count = count
+ )
)
- ))
+ )
}
}
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params,
- id = id,
- format = format,
- throttle = throttle
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ params = params,
+ id = id,
+ format = format,
+ throttle = throttle
+ )
+ )
+ )
override def specIncludeAnnotatedNode(
a: In,
@@ -607,11 +665,8 @@ object ExpandTemplates extends AstTransformer
aNode: Ast.Annotated[AstNode[Ast.SpecInit]]
) =
val data = aNode._2.data
- for (result <- matchExprNode(a, data.phase))
- yield {
- val (_, phase1) = result
- ((), cloneAnnotatedNode(a, aNode, data.copy(phase=phase1)))
- }
+ for ((_, phase) <- matchExprNode(a, data.phase))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(phase=phase)))
override def specInternalPortAnnotatedNode(
a: In,
@@ -621,10 +676,17 @@ object ExpandTemplates extends AstTransformer
for {
params <- formalParamList(a, data.params)
priority <- exprNodeOpt(a, data.priority)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params,
- priority = priority,
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ params = params,
+ priority = priority,
+ )
+ )
+ )
override def specLocAnnotatedNode(
a: In,
@@ -634,10 +696,14 @@ object ExpandTemplates extends AstTransformer
for {
symbol <- qualIdentNode(a, data.symbol)
(_, file) <- defaultNode(a, data.file)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- symbol = symbol,
- file = file
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(symbol = symbol, file = file)
+ )
+ )
override def specParamAnnotatedNode(
a: In,
@@ -650,13 +716,20 @@ object ExpandTemplates extends AstTransformer
id <- exprNodeOpt(a, data.id)
setOpcode <- exprNodeOpt(a, data.setOpcode)
saveOpcode <- exprNodeOpt(a, data.saveOpcode)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- typeName = typeName,
- default = default,
- id = id,
- setOpcode = setOpcode,
- saveOpcode = saveOpcode
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ typeName = typeName,
+ default = default,
+ id = id,
+ setOpcode = setOpcode,
+ saveOpcode = saveOpcode
+ )
+ )
+ )
override def specPortInstanceAnnotatedNode(
a: In,
@@ -670,23 +743,35 @@ object ExpandTemplates extends AstTransformer
port <- qualIdentNodeOpt(a, data.port)
priority <- exprNodeOpt(a, data.priority)
queueFull <- defaultNodeOpt(a, data.queueFull)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- size = size,
- port = port,
- priority = priority,
- queueFull = queueFull
- )))
- }
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ size = size,
+ port = port,
+ priority = priority,
+ queueFull = queueFull
+ )
+ )
+ )
case data @ Ast.SpecPortInstance.Special(_, _, _, _, _) =>
for {
priority <- exprNodeOpt(a, data.priority)
queueFull <- defaultNodeOpt(a, data.queueFull)
} yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- priority = priority,
- queueFull = queueFull
- )))
+ (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ priority = priority,
+ queueFull = queueFull
+ )
+ )
+ )
}
}
@@ -698,10 +783,14 @@ object ExpandTemplates extends AstTransformer
for {
(_, port1) <- defaultNode(a, data.port1)
(_, port2) <- defaultNode(a, data.port2)
- } yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- port1 = port1,
- port2 = port2
- ))))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(port1 = port1, port2 = port2)
+ )
+ )
override def specRecordAnnotatedNode(
a: In,
@@ -711,10 +800,14 @@ object ExpandTemplates extends AstTransformer
for {
(_, recordType) <- matchTypeName(a, data.recordType)
id <- exprNodeOpt(a, data.id)
- } yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- recordType = recordType,
- id = id
- ))))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(recordType = recordType, id = id)
+ )
+ )
override def specStateMachineInstanceAnnotatedNode(
a: In,
@@ -724,10 +817,14 @@ object ExpandTemplates extends AstTransformer
for {
stateMachine <- qualIdentNode(a, data.stateMachine)
priority <- exprNodeOpt(a, data.priority)
- } yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- stateMachine = stateMachine,
- priority = priority
- ))))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(stateMachine = stateMachine, priority = priority)
+ )
+ )
override def specTlmChannelAnnotatedNode(
a: In,
@@ -742,7 +839,7 @@ object ExpandTemplates extends AstTransformer
for {
(_, kind) <- defaultNode(a, kind)
(_, value) <- matchExprNode(a, value)
- } yield (((), (kind, value)))
+ } yield ((), (kind, value))
}
for {
@@ -750,13 +847,20 @@ object ExpandTemplates extends AstTransformer
id <- exprNodeOpt(a, data.id)
low <- transformList(a, data.low, limit)
high <- transformList(a, data.high, limit)
- } yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- typeName = typeName,
- id = id,
- format = cloneStringNodeOpt(a, data.format),
- low = low,
- high = high
- ))))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ typeName = typeName,
+ id = id,
+ format = cloneStringNodeOpt(a, data.format),
+ low = low,
+ high = high
+ )
+ )
+ )
override def specTlmPacketAnnotatedNode(
a: In,
@@ -770,19 +874,29 @@ object ExpandTemplates extends AstTransformer
member match {
case Ast.TlmPacketMember.SpecInclude(node) =>
for ((_, file) <- defaultNode(a, node.data.file))
- yield ((), Ast.TlmPacketMember.SpecInclude(
- cloneNode(a, node, node.data.copy(file = file))
- ))
+ yield (
+ (),
+ Ast.TlmPacketMember.SpecInclude(
+ cloneNode(a, node, node.data.copy(file = file))
+ )
+ )
case Ast.TlmPacketMember.TlmChannelIdentifier(node) =>
for {
componentInstance <- qualIdentNode(a, node.data.componentInstance)
(_, channelName) <- defaultNode(a, node.data.channelName)
- } yield ((), Ast.TlmPacketMember.TlmChannelIdentifier(
- cloneNode(a, node, node.data.copy(
- componentInstance = componentInstance,
- channelName = channelName
- ))
- ))
+ } yield (
+ (),
+ Ast.TlmPacketMember.TlmChannelIdentifier(
+ cloneNode(
+ a,
+ node,
+ node.data.copy(
+ componentInstance = componentInstance,
+ channelName = channelName
+ )
+ )
+ )
+ )
}
}
@@ -790,11 +904,18 @@ object ExpandTemplates extends AstTransformer
id <- exprNodeOpt(a, data.id)
(_, group) <- matchExprNode(a, data.group)
members <- transformList(a, data.members, tlmPacketMember)
- } yield (((), cloneAnnotatedNode(a, aNode, data.copy(
- id = id,
- group = group,
- members = members
- ))))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ id = id,
+ group = group,
+ members = members
+ )
+ )
+ )
override def specTopPortAnnotatedNode(
a: In,
@@ -802,14 +923,14 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for (underlyingPort <- portInstanceIdentifierNode(a, data.underlyingPort))
- yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(underlyingPort = underlyingPort)
+ yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(underlyingPort = underlyingPort)
+ )
)
- )
override def specTlmPacketSetAnnotatedNode(
a: In,
@@ -824,18 +945,29 @@ object ExpandTemplates extends AstTransformer
for {
componentInstance <- qualIdentNode(a, data.componentInstance)
(_, channelName) <- defaultNode(a, data.channelName)
- } yield ((), cloneNode(a, node, data.copy(
- componentInstance = componentInstance,
- channelName = channelName
- )))
+ } yield (
+ (),
+ cloneNode(
+ a,
+ node,
+ data.copy(
+ componentInstance = componentInstance,
+ channelName = channelName
+ )
+ )
+ )
for {
members <- transformFlatList(a, data.members, matchTlmPacketSetMember)
omitted <- transformList(a, data.omitted, tlmChannelIdentifier)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- members = members,
- omitted = omitted
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(members = members, omitted = omitted)
+ )
+ )
override def specInterfaceImportAnnotatedNode(
a: In,
@@ -844,9 +976,14 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
sym <- qualIdentNode(a, data.sym)
- } yield ((), cloneAnnotatedNode(a, aNode, data.copy(
- sym = sym
- )))
+ } yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(sym = sym)
+ )
+ )
override def defModuleTemplateAnnotatedNode(
a: In,
@@ -871,16 +1008,6 @@ object ExpandTemplates extends AstTransformer
yield data.copy(interface = interface)
}
} yield ((), cloneAnnotatedNode(a, param, data))
-// node.data match {
-// case data @ Ast.TemplateParam.Constant(_, tn) =>
-// for ((_, tn) <- matchTypeName(a, tn))
-// yield ((), cloneAnnotatedNode(a, param, data.copy(typeName = tn)))
-// case data @ Ast.TemplateParam.Type(_) =>
-// Right(((), cloneAnnotatedNode(a, param, data)))
-// case data @ Ast.TemplateParam.Interface(_, interface) =>
-// for (interface <- qualIdentNode(a, interface))
-// yield ((), cloneAnnotatedNode(a, param, data.copy(interface = interface)))
-// }
}
for {
@@ -889,12 +1016,14 @@ object ExpandTemplates extends AstTransformer
members <- transformFlatList(a, data.members, matchModuleMember)
a <- Right(a.copy(templateDefId = None))
}
- yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(
- params = params,
- members = members
- )))
- }
+ yield (
+ (),
+ cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(params = params, members = members)
+ )
+ )
override def defModuleAnnotatedNode(
a: Analysis,
@@ -909,7 +1038,7 @@ object ExpandTemplates extends AstTransformer
override def specTemplateExpandAnnotatedNode(
a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
- ): ResultAnnotatedNode[Ast.SpecTemplateExpand] = {
+ ) = {
val (_, node, _) = aNode
val data = node.data
data.members match {
@@ -930,12 +1059,15 @@ object ExpandTemplates extends AstTransformer
case Some(expansionNode) => {
val out = AstNode.create(data)
val inLoc = Locations.get(node.id)
- Locations.put(out.id, Location(
- inLoc.file,
- inLoc.pos,
- inLoc.includingLoc,
- Some(Locations.get(expansionNode))
- ))
+ Locations.put(
+ out.id,
+ Location(
+ inLoc.file,
+ inLoc.pos,
+ inLoc.includingLoc,
+ Some(Locations.get(expansionNode))
+ )
+ )
out
}
}
@@ -955,10 +1087,14 @@ object ExpandTemplates extends AstTransformer
): AstNode[Ast.QualIdent] = {
node.data match {
case Ast.QualIdent.Qualified(qualifier, name) =>
- cloneNode(a, node, Ast.QualIdent.Qualified(
- cloneQualIdentNode(a, qualifier),
- cloneNode(a, name, name.data)
- ))
+ cloneNode(
+ a,
+ node,
+ Ast.QualIdent.Qualified(
+ cloneQualIdentNode(a, qualifier),
+ cloneNode(a, name, name.data)
+ )
+ )
case Ast.QualIdent.Unqualified(name, isAbsolute) =>
cloneNode(a, node, Ast.QualIdent.Unqualified(name, isAbsolute))
}
@@ -981,7 +1117,7 @@ object ExpandTemplates extends AstTransformer
case None => Right(None)
case Some(node) =>
for ((_, node) <- defaultNode(a, node))
- yield Some(node)
+ yield Some(node)
}
private def defEnumConstantAnnotatedNode(
@@ -990,7 +1126,7 @@ object ExpandTemplates extends AstTransformer
): Result.Result[Ast.Annotated[AstNode[Ast.DefEnumConstant]]] =
val data = aNode._2.data
for (value <- exprNodeOpt(a, data.value))
- yield cloneAnnotatedNode(a, aNode, data.copy(value = value))
+ yield cloneAnnotatedNode(a, aNode, data.copy(value = value))
/** Expand a template */
private def expandTemplate(
@@ -1027,7 +1163,7 @@ object ExpandTemplates extends AstTransformer
case None => Right(None)
case Some(value) =>
for ((_, result) <- matchExprNode(a, value))
- yield Some(result)
+ yield Some(result)
}
private def formalAnnotatatedParam(
@@ -1036,7 +1172,7 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for ((_, ty) <- matchTypeName(a, data.typeName))
- yield cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
+ yield cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
private def formalParamList(
a: In,
@@ -1051,10 +1187,14 @@ object ExpandTemplates extends AstTransformer
for {
interfaceInstance <- qualIdentNode(a, pii.data.interfaceInstance)
(_, portName) <- defaultNode(a, pii.data.portName)
- } yield cloneNode(a, pii, pii.data.copy(
- interfaceInstance = interfaceInstance,
- portName = portName
- ))
+ } yield cloneNode(
+ a,
+ pii,
+ pii.data.copy(
+ interfaceInstance = interfaceInstance,
+ portName = portName
+ )
+ )
}
private def qualIdentNode(
@@ -1071,7 +1211,7 @@ object ExpandTemplates extends AstTransformer
case None => Right(None)
case Some(value) =>
for (result <- qualIdentNode(a, value))
- yield Some(result)
+ yield Some(result)
}
}
@@ -1084,12 +1224,11 @@ object ExpandTemplates extends AstTransformer
node: AstNode[Ast.StructMember]
) = {
for ((_, value) <- matchExprNode(a, node.data.value))
- yield {
- cloneNode(a, node, Ast.StructMember(
- node.data.name,
- value
- ))
- }
+ yield cloneNode(
+ a,
+ node,
+ Ast.StructMember(node.data.name, value)
+ )
}
private def structTypeMemberAnnotatedNode(
@@ -1100,13 +1239,15 @@ object ExpandTemplates extends AstTransformer
for {
size <- exprNodeOpt(a, data.size)
(_, typeName) <- matchTypeName(a, data.typeName)
- } yield {
- cloneAnnotatedNode(a, aNode, data.copy(
- size = size,
- typeName = typeName,
- format = cloneStringNodeOpt(a, data.format)
- ))
- }
+ } yield cloneAnnotatedNode(
+ a,
+ aNode,
+ data.copy(
+ size = size,
+ typeName = typeName,
+ format = cloneStringNodeOpt(a, data.format)
+ )
+ )
private def transitionExpr(
a: In,
@@ -1115,10 +1256,11 @@ object ExpandTemplates extends AstTransformer
for {
actions <- transformList(a, node.data.actions, defaultNode)
target <- qualIdentNode(a, node.data.target)
- } yield cloneNode(a, node, node.data.copy(
- actions = actions,
- target = target
- ))
+ } yield cloneNode(
+ a,
+ node,
+ node.data.copy(actions = actions, target = target)
+ )
private def transitionOrDo(
a: In,
@@ -1127,10 +1269,10 @@ object ExpandTemplates extends AstTransformer
transitionOrDo match
case Ast.TransitionOrDo.Transition(transition) =>
for (result <- transitionExpr(a, transition))
- yield Ast.TransitionOrDo.Transition(result)
+ yield Ast.TransitionOrDo.Transition(result)
case Ast.TransitionOrDo.Do(actions) =>
for (result <- transformList(a, actions, defaultNode))
- yield Ast.TransitionOrDo.Do(result)
+ yield Ast.TransitionOrDo.Do(result)
private def typeNameNodeOpt(
a: In,
@@ -1140,7 +1282,7 @@ object ExpandTemplates extends AstTransformer
case None => Right(None)
case Some(tn) =>
for ((_, tn) <- matchTypeName(a, tn))
- yield Some(tn)
+ yield Some(tn)
}
From 3895d4d07eb43208f734f2b07559ee0e675e1b99 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 00:38:24 -0700
Subject: [PATCH 19/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 46 ++++++++-----------
1 file changed, 18 insertions(+), 28 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index cca90307a..370346a5c 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -15,7 +15,7 @@ object ExpandTemplates extends AstTransformer
type Out = Unit
def default(a: Analysis) =
- throw new InternalError("ExpandTemplates: Transformer not implemented")
+ throw InternalError("ExpandTemplates: Transformer not implemented")
/** Transform a list in sequence, threading state */
def transformList[A, B](
@@ -78,7 +78,8 @@ object ExpandTemplates extends AstTransformer
aNode: Ast.Annotated[AstNode[T]]
) = {
a.templateExpansionId match {
- // We are not currently in a template, leave the node alone
+ // We are not currently in a template expansion.
+ // Leave the node alone.
case None => Right((), aNode)
case Some(_) =>
val (pre, node, post) = aNode
@@ -92,7 +93,7 @@ object ExpandTemplates extends AstTransformer
node: AstNode[Ast.Expr],
e: Ast.ExprArray
) =
- for { result <- transformList(a, e.elts, matchExprNode) }
+ for (result <- transformList(a, e.elts, matchExprNode))
yield ((), cloneNode(a, node, Ast.ExprArray(result)))
override def exprArraySubscriptNode(
@@ -352,9 +353,7 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
typeName <- typeNameNodeOpt(a, data.typeName)
- } yield {
- ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
- }
+ } yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
override def defChoiceAnnotatedNode(
a: In,
@@ -618,24 +617,19 @@ object ExpandTemplates extends AstTransformer
params <- formalParamList(a, data.params)
id <- exprNodeOpt(a, data.id)
(_, format) <- defaultNode(a, data.format)
- throttle <- {
- data.throttle match {
- case None => Right(None)
- case Some(throttle) =>
- for {
- (_, count) <- matchExprNode(a, throttle.data.count)
- every <- exprNodeOpt(a, throttle.data.every)
- } yield Some(
- cloneNode(
- a,
- throttle,
- throttle.data.copy(
- every = every,
- count = count
- )
- )
+ throttle <- data.throttle match {
+ case None => Right(None)
+ case Some(throttle) =>
+ for {
+ (_, count) <- matchExprNode(a, throttle.data.count)
+ every <- exprNodeOpt(a, throttle.data.every)
+ } yield Some(
+ cloneNode(
+ a,
+ throttle,
+ throttle.data.copy(every = every, count = count)
)
- }
+ )
}
} yield (
(),
@@ -681,10 +675,7 @@ object ExpandTemplates extends AstTransformer
cloneAnnotatedNode(
a,
aNode,
- data.copy(
- params = params,
- priority = priority,
- )
+ data.copy(params = params, priority = priority)
)
)
@@ -1285,5 +1276,4 @@ object ExpandTemplates extends AstTransformer
yield Some(tn)
}
-
}
From c36ae19fe53348d7046ed12b444ebf2567ee4984 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 00:47:10 -0700
Subject: [PATCH 20/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 76 ++++++++-----------
1 file changed, 31 insertions(+), 45 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 370346a5c..421832d5a 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -200,18 +200,16 @@ object ExpandTemplates extends AstTransformer
(_, size) <- matchExprNode(a, data.size)
(_, eltType) <- matchTypeName(a, data.eltType)
default <- exprNodeOpt(a, data.default)
- } yield (
- (),
- cloneAnnotatedNode(
- a, aNode,
- data.copy(
- size = size,
- eltType = eltType,
- default = default,
- format = cloneStringNodeOpt(a, data.format)
- )
+ } yield {
+ val dataCopy = data.copy(
+ size = size,
+ eltType = eltType,
+ default = default,
+ format = cloneStringNodeOpt(a, data.format)
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
}
override def defComponentAnnotatedNode(
@@ -332,9 +330,9 @@ object ExpandTemplates extends AstTransformer
aNode: Ast.Annotated[AstNode[Ast.DefStateMachine]],
members: List[Ast.StateMachineMember]
) =
- val data = aNode._2.data
- for (members <- transformFlatList(a, members, matchStateMachineMember))
- yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = Some(members))))
+ val data = aNode._2.data
+ for (members <- transformFlatList(a, members, matchStateMachineMember))
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = Some(members))))
override def defStateMachineAnnotatedNode(
a: In,
@@ -551,40 +549,34 @@ object ExpandTemplates extends AstTransformer
fromIndex <- exprNodeOpt(a, connection.fromIndex)
toPort <- portInstanceIdentifierNode(a, connection.toPort)
toIndex <- exprNodeOpt(a, connection.toIndex)
- } yield (
- (),
- connection.copy(
+ } yield {
+ val connectionCopy = connection.copy(
fromPort = fromPort,
fromIndex = fromIndex,
toPort = toPort,
toIndex = toIndex
)
- )
+ ((), connectionCopy)
+ }
}
data match {
case data @ Ast.SpecConnectionGraph.Direct(_, connections) =>
for (connections <- transformList(a, connections, connection))
- yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(connections = connections)
- )
- )
+ yield {
+ val dataCopy = data.copy(connections = connections)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
case data @ Ast.SpecConnectionGraph.Pattern(_, source, targets) =>
for {
source <- qualIdentNode(a, source)
targets <- transformList(a, targets, resultAdapter(qualIdentNode))
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(source = source, targets = targets)
- )
- )
+ } yield {
+ val dataCopy = data.copy(source = source, targets = targets)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
}
@@ -596,17 +588,11 @@ object ExpandTemplates extends AstTransformer
for {
id <- exprNodeOpt(a, data.id)
defaultPriority <- exprNodeOpt(a, data.defaultPriority)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- id = id,
- defaultPriority = defaultPriority
- )
- )
- )
+ } yield {
+ val dataCopy = data.copy(id = id, defaultPriority = defaultPriority)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specEventAnnotatedNode(
a: In,
From bab45e5634d2f4b7ae18a7551065b98906525c15 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 00:54:57 -0700
Subject: [PATCH 21/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 56 +++++++++----------
1 file changed, 25 insertions(+), 31 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 421832d5a..dfe87578e 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -60,15 +60,13 @@ object ExpandTemplates extends AstTransformer
case Some(expansionNode) => {
val out = AstNode.create(node.data)
val inLoc = Locations.get(node.id)
- Locations.put(
- out.id,
- Location(
- inLoc.file,
- inLoc.pos,
- inLoc.includingLoc,
- Some(Locations.get(expansionNode))
- )
+ val outLoc = Location(
+ inLoc.file,
+ inLoc.pos,
+ inLoc.includingLoc,
+ Some(Locations.get(expansionNode))
)
+ Locations.put(out.id, outLoc)
Right((), out)
}
}
@@ -234,23 +232,21 @@ object ExpandTemplates extends AstTransformer
priority <- exprNodeOpt(a, data.priority)
cpu <- exprNodeOpt(a, data.cpu)
initSpecs <- transformList(a, data.initSpecs, specInitAnnotatedNode)
- } yield (
- (),
- cloneAnnotatedNode(
- a, aNode,
- data.copy(
- component=component,
- baseId=baseId,
- implType=cloneStringNodeOpt(a, data.implType),
- file=cloneStringNodeOpt(a, data.file),
- queueSize=queueSize,
- stackSize=stackSize,
- priority=priority,
- cpu=cpu,
- initSpecs=initSpecs
- )
+ } yield {
+ val dataCopy = data.copy(
+ component=component,
+ baseId=baseId,
+ implType=cloneStringNodeOpt(a, data.implType),
+ file=cloneStringNodeOpt(a, data.file),
+ queueSize=queueSize,
+ stackSize=stackSize,
+ priority=priority,
+ cpu=cpu,
+ initSpecs=initSpecs
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
}
override def defInterfaceAnnotatedNode(
@@ -268,13 +264,11 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for ((_, value) <- matchExprNode(a, data.value))
- yield (
- (),
- cloneAnnotatedNode(
- a, aNode,
- data.copy(value = value)
- )
- )
+ yield {
+ val dataCopy = data.copy(value = value)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defEnumAnnotatedNode(
a: In,
From be387f3988cb25e29823c6302561e2e4582807ca Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 00:59:27 -0700
Subject: [PATCH 22/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 46 +++++++++----------
1 file changed, 22 insertions(+), 24 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index dfe87578e..932d7312a 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -54,22 +54,22 @@ object ExpandTemplates extends AstTransformer
override def defaultNode[T](
a: Analysis,
node: AstNode[T]
- ) =
- a.templateExpansionId match {
- case None => Right((), node)
- case Some(expansionNode) => {
- val out = AstNode.create(node.data)
- val inLoc = Locations.get(node.id)
- val outLoc = Location(
- inLoc.file,
- inLoc.pos,
- inLoc.includingLoc,
- Some(Locations.get(expansionNode))
- )
- Locations.put(out.id, outLoc)
- Right((), out)
- }
- }
+ ) = Right((), cloneNode(a, node, node.data))
+// a.templateExpansionId match {
+// case None => Right((), node)
+// case Some(expansionNode) => {
+// val out = AstNode.create(node.data)
+// val inLoc = Locations.get(node.id)
+// val outLoc = Location(
+// inLoc.file,
+// inLoc.pos,
+// inLoc.includingLoc,
+// Some(Locations.get(expansionNode))
+// )
+// Locations.put(out.id, outLoc)
+// Right((), out)
+// }
+// }
override def defaultAnnotatedNode[T](
a: In,
@@ -1030,15 +1030,13 @@ object ExpandTemplates extends AstTransformer
case Some(expansionNode) => {
val out = AstNode.create(data)
val inLoc = Locations.get(node.id)
- Locations.put(
- out.id,
- Location(
- inLoc.file,
- inLoc.pos,
- inLoc.includingLoc,
- Some(Locations.get(expansionNode))
- )
+ val outLoc = Location(
+ inLoc.file,
+ inLoc.pos,
+ inLoc.includingLoc,
+ Some(Locations.get(expansionNode))
)
+ Locations.put(out.id, outLoc)
out
}
}
From a3f73404012654256144265163dc3a7c481f96d4 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 01:07:22 -0700
Subject: [PATCH 23/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 69 +++++++------------
1 file changed, 23 insertions(+), 46 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 932d7312a..18af8ae67 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -55,21 +55,6 @@ object ExpandTemplates extends AstTransformer
a: Analysis,
node: AstNode[T]
) = Right((), cloneNode(a, node, node.data))
-// a.templateExpansionId match {
-// case None => Right((), node)
-// case Some(expansionNode) => {
-// val out = AstNode.create(node.data)
-// val inLoc = Locations.get(node.id)
-// val outLoc = Location(
-// inLoc.file,
-// inLoc.pos,
-// inLoc.includingLoc,
-// Some(Locations.get(expansionNode))
-// )
-// Locations.put(out.id, outLoc)
-// Right((), out)
-// }
-// }
override def defaultAnnotatedNode[T](
a: In,
@@ -283,18 +268,15 @@ object ExpandTemplates extends AstTransformer
resultAdapter(defEnumConstantAnnotatedNode)
)
default <- exprNodeOpt(a, data.default)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- typeName = typeName,
- constants = constants,
- default = default
- )
+ } yield {
+ val dataCopy = data.copy(
+ typeName = typeName,
+ constants = constants,
+ default = default
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defPortAnnotatedNode(
a: In,
@@ -304,14 +286,11 @@ object ExpandTemplates extends AstTransformer
for {
params <- formalParamList(a, data.params)
returnType <- typeNameNodeOpt(a, data.returnType)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(params = params, returnType = returnType)
- )
- )
+ } yield {
+ val dataCopy = data.copy(params = params, returnType = returnType)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defStateMachineAnnotatedNodeExternal(
in: In,
@@ -356,18 +335,15 @@ object ExpandTemplates extends AstTransformer
(_, guard) <- defaultNode(a, data.guard)
ifTransition <- transitionExpr(a, data.ifTransition)
elseTransition <- transitionExpr(a, data.elseTransition)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- guard = guard,
- ifTransition = ifTransition,
- elseTransition = elseTransition
- )
+ } yield {
+ val dataCopy = data.copy(
+ guard = guard,
+ ifTransition = ifTransition,
+ elseTransition = elseTransition
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defGuardAnnotatedNode(
a: In,
@@ -531,7 +507,7 @@ object ExpandTemplates extends AstTransformer
override def specConnectionGraphAnnotatedNode(
a: In,
aNode: Ast.Annotated[AstNode[Ast.SpecConnectionGraph]]
- ) =
+ ) = {
val data = aNode._2.data
def connection(
@@ -573,6 +549,7 @@ object ExpandTemplates extends AstTransformer
}
}
+ }
override def specContainerAnnotatedNode(
a: In,
From c99182f1696b8dd9248afd5134d394e1030b0228 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 07:49:44 -0700
Subject: [PATCH 24/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 139 +++++++-----------
1 file changed, 56 insertions(+), 83 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 18af8ae67..f9af57a10 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -144,11 +144,10 @@ object ExpandTemplates extends AstTransformer
a: In,
node: AstNode[Ast.TypeName],
tn: Ast.TypeNameQualIdent
- ) =
- Right(
- (),
- cloneNode(a, node, Ast.TypeNameQualIdent(cloneQualIdentNode(a, tn.name)))
- )
+ ) = {
+ val qidNode = cloneQualIdentNode(a, tn.name)
+ Right((), cloneNode(a, node, Ast.TypeNameQualIdent(qidNode)))
+ }
override def typeNameStringNode(
a: In,
@@ -169,10 +168,7 @@ object ExpandTemplates extends AstTransformer
): ResultAnnotatedNode[Ast.DefAliasType] =
val data = aNode._2.data
for ((_, ty) <- matchTypeName(a, data.typeName))
- yield (
- (),
- cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
- )
+ yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = ty)))
override def defArrayAnnotatedNode(
a: In,
@@ -402,18 +398,15 @@ object ExpandTemplates extends AstTransformer
(_, signal) <- defaultNode(a, data.signal)
guard <- defaultNodeOpt(a, data.guard)
transitionOrDo <- transitionOrDo(a, data.transitionOrDo)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- signal = signal,
- guard = guard,
- transitionOrDo = transitionOrDo
- )
+ } yield {
+ val dataCopy = data.copy(
+ signal = signal,
+ guard = guard,
+ transitionOrDo = transitionOrDo
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defStructAnnotatedNode(
a: In,
@@ -423,14 +416,11 @@ object ExpandTemplates extends AstTransformer
for {
members <- transformList(a, data.members, resultAdapter(structTypeMemberAnnotatedNode))
default <- exprNodeOpt(a, data.default)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(members = members, default = default)
- )
- )
+ } yield {
+ val dataCopy = data.copy(members = members, default = default)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defTopologyAnnotatedNode(
a: In,
@@ -440,14 +430,11 @@ object ExpandTemplates extends AstTransformer
for {
members <- transformFlatList(a, data.members, matchTopologyMember)
implements <- transformList(a, data.implements, (a, q) => Right(((), cloneQualIdentNode(a, q))))
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(members = members, implements = implements)
- )
- )
+ } yield {
+ val dataCopy = data.copy(members = members, implements = implements)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defSystemAnnotatedNode(
a: In,
@@ -455,14 +442,11 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for (topology <- qualIdentNode(a, data.topology))
- yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(topology = topology)
- )
- )
+ yield {
+ val dataCopy = data.copy(topology = topology)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specCommandAnnotatedNode(
a: In,
@@ -474,19 +458,16 @@ object ExpandTemplates extends AstTransformer
opcode <- exprNodeOpt(a, data.opcode)
priority <- exprNodeOpt(a, data.priority)
queueFull <- defaultNodeOpt(a, data.queueFull)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- params = params,
- opcode = opcode,
- priority = priority,
- queueFull = queueFull,
- )
+ } yield {
+ val dataCopy = data.copy(
+ params = params,
+ opcode = opcode,
+ priority = priority,
+ queueFull = queueFull,
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specInstanceAnnotatedNode(
a: In,
@@ -580,27 +561,22 @@ object ExpandTemplates extends AstTransformer
for {
(_, count) <- matchExprNode(a, throttle.data.count)
every <- exprNodeOpt(a, throttle.data.every)
- } yield Some(
- cloneNode(
- a,
- throttle,
- throttle.data.copy(every = every, count = count)
- )
- )
+ } yield {
+ val dataCopy = throttle.data.copy(every = every, count = count)
+ val node = cloneNode(a, throttle, dataCopy)
+ Some(node)
+ }
}
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- params = params,
- id = id,
- format = format,
- throttle = throttle
- )
+ } yield {
+ val dataCopy = data.copy(
+ params = params,
+ id = id,
+ format = format,
+ throttle = throttle
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specIncludeAnnotatedNode(
a: In,
@@ -627,14 +603,11 @@ object ExpandTemplates extends AstTransformer
for {
params <- formalParamList(a, data.params)
priority <- exprNodeOpt(a, data.priority)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(params = params, priority = priority)
- )
- )
+ } yield {
+ val dataCopy = data.copy(params = params, priority = priority)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specLocAnnotatedNode(
a: In,
From 7404f063cd9f8128f1948e77c42af16cf626e2df Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 08:03:02 -0700
Subject: [PATCH 25/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 200 +++++++-----------
1 file changed, 80 insertions(+), 120 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index f9af57a10..4aa206a88 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -476,14 +476,11 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
instance <- qualIdentNode(a, data.instance)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(instance = instance)
- )
- )
+ } yield {
+ val dataCopy = data.copy(instance = instance)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specConnectionGraphAnnotatedNode(
a: In,
@@ -617,14 +614,11 @@ object ExpandTemplates extends AstTransformer
for {
symbol <- qualIdentNode(a, data.symbol)
(_, file) <- defaultNode(a, data.file)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(symbol = symbol, file = file)
- )
- )
+ } yield {
+ val dataCopy = data.copy(symbol = symbol, file = file)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specParamAnnotatedNode(
a: In,
@@ -637,20 +631,17 @@ object ExpandTemplates extends AstTransformer
id <- exprNodeOpt(a, data.id)
setOpcode <- exprNodeOpt(a, data.setOpcode)
saveOpcode <- exprNodeOpt(a, data.saveOpcode)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- typeName = typeName,
- default = default,
- id = id,
- setOpcode = setOpcode,
- saveOpcode = saveOpcode
- )
+ } yield {
+ val dataCopy = data.copy(
+ typeName = typeName,
+ default = default,
+ id = id,
+ setOpcode = setOpcode,
+ saveOpcode = saveOpcode
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specPortInstanceAnnotatedNode(
a: In,
@@ -658,41 +649,30 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
data match {
- case data @ Ast.SpecPortInstance.General(_, _, _, _, _, _) =>
+ case data : Ast.SpecPortInstance.General =>
for {
size <- exprNodeOpt(a, data.size)
port <- qualIdentNodeOpt(a, data.port)
priority <- exprNodeOpt(a, data.priority)
queueFull <- defaultNodeOpt(a, data.queueFull)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- size = size,
- port = port,
- priority = priority,
- queueFull = queueFull
- )
+ } yield {
+ val dataCopy = data.copy(
+ size = size,
+ port = port,
+ priority = priority,
+ queueFull = queueFull
)
- )
- case data @ Ast.SpecPortInstance.Special(_, _, _, _, _) =>
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
+ case data : Ast.SpecPortInstance.Special =>
for {
priority <- exprNodeOpt(a, data.priority)
queueFull <- defaultNodeOpt(a, data.queueFull)
} yield {
- (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- priority = priority,
- queueFull = queueFull
- )
- )
- )
+ val dataCopy = data.copy(priority = priority, queueFull = queueFull)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
}
}
@@ -704,14 +684,11 @@ object ExpandTemplates extends AstTransformer
for {
(_, port1) <- defaultNode(a, data.port1)
(_, port2) <- defaultNode(a, data.port2)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(port1 = port1, port2 = port2)
- )
- )
+ } yield {
+ val dataCopy = data.copy(port1 = port1, port2 = port2)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specRecordAnnotatedNode(
a: In,
@@ -721,14 +698,11 @@ object ExpandTemplates extends AstTransformer
for {
(_, recordType) <- matchTypeName(a, data.recordType)
id <- exprNodeOpt(a, data.id)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(recordType = recordType, id = id)
- )
- )
+ } yield {
+ val dataCopy = data.copy(recordType = recordType, id = id)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specStateMachineInstanceAnnotatedNode(
a: In,
@@ -738,14 +712,11 @@ object ExpandTemplates extends AstTransformer
for {
stateMachine <- qualIdentNode(a, data.stateMachine)
priority <- exprNodeOpt(a, data.priority)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(stateMachine = stateMachine, priority = priority)
- )
- )
+ } yield {
+ val dataCopy = data.copy(stateMachine = stateMachine, priority = priority)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specTlmChannelAnnotatedNode(
a: In,
@@ -768,20 +739,17 @@ object ExpandTemplates extends AstTransformer
id <- exprNodeOpt(a, data.id)
low <- transformList(a, data.low, limit)
high <- transformList(a, data.high, limit)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- typeName = typeName,
- id = id,
- format = cloneStringNodeOpt(a, data.format),
- low = low,
- high = high
- )
+ } yield {
+ val dataCopy = data.copy(
+ typeName = typeName,
+ id = id,
+ format = cloneStringNodeOpt(a, data.format),
+ low = low,
+ high = high
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specTlmPacketAnnotatedNode(
a: In,
@@ -795,29 +763,24 @@ object ExpandTemplates extends AstTransformer
member match {
case Ast.TlmPacketMember.SpecInclude(node) =>
for ((_, file) <- defaultNode(a, node.data.file))
- yield (
- (),
- Ast.TlmPacketMember.SpecInclude(
- cloneNode(a, node, node.data.copy(file = file))
- )
- )
+ yield {
+ val nodeCopy = cloneNode(a, node, node.data.copy(file = file))
+ val specIncludeCopy = Ast.TlmPacketMember.SpecInclude(nodeCopy)
+ ((), specIncludeCopy)
+ }
case Ast.TlmPacketMember.TlmChannelIdentifier(node) =>
for {
componentInstance <- qualIdentNode(a, node.data.componentInstance)
(_, channelName) <- defaultNode(a, node.data.channelName)
- } yield (
- (),
- Ast.TlmPacketMember.TlmChannelIdentifier(
- cloneNode(
- a,
- node,
- node.data.copy(
- componentInstance = componentInstance,
- channelName = channelName
- )
- )
+ } yield {
+ val dataCopy = node.data.copy(
+ componentInstance = componentInstance,
+ channelName = channelName
)
- )
+ val nodeCopy = cloneNode(a, node, dataCopy)
+ val channelIdCopy = Ast.TlmPacketMember.TlmChannelIdentifier(nodeCopy)
+ ((), channelIdCopy)
+ }
}
}
@@ -825,18 +788,15 @@ object ExpandTemplates extends AstTransformer
id <- exprNodeOpt(a, data.id)
(_, group) <- matchExprNode(a, data.group)
members <- transformList(a, data.members, tlmPacketMember)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- id = id,
- group = group,
- members = members
- )
+ } yield {
+ val dataCopy = data.copy(
+ id = id,
+ group = group,
+ members = members
)
- )
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specTopPortAnnotatedNode(
a: In,
From 14c498ef4dd569c9b56022f81ef93350421192eb Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 08:11:42 -0700
Subject: [PATCH 26/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 80 +++++++------------
1 file changed, 31 insertions(+), 49 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 4aa206a88..4ae251685 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -804,14 +804,11 @@ object ExpandTemplates extends AstTransformer
) =
val data = aNode._2.data
for (underlyingPort <- portInstanceIdentifierNode(a, data.underlyingPort))
- yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(underlyingPort = underlyingPort)
- )
- )
+ yield {
+ val dataCopy = data.copy(underlyingPort = underlyingPort)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specTlmPacketSetAnnotatedNode(
a: In,
@@ -826,29 +823,23 @@ object ExpandTemplates extends AstTransformer
for {
componentInstance <- qualIdentNode(a, data.componentInstance)
(_, channelName) <- defaultNode(a, data.channelName)
- } yield (
- (),
- cloneNode(
- a,
- node,
- data.copy(
- componentInstance = componentInstance,
- channelName = channelName
- )
+ } yield {
+ val dataCopy = data.copy(
+ componentInstance = componentInstance,
+ channelName = channelName
)
- )
+ val nodeCopy = cloneNode(a, node, dataCopy)
+ ((), nodeCopy)
+ }
for {
members <- transformFlatList(a, data.members, matchTlmPacketSetMember)
omitted <- transformList(a, data.omitted, tlmChannelIdentifier)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(members = members, omitted = omitted)
- )
- )
+ } yield {
+ val dataCopy = data.copy(members = members, omitted = omitted)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def specInterfaceImportAnnotatedNode(
a: In,
@@ -857,14 +848,11 @@ object ExpandTemplates extends AstTransformer
val data = aNode._2.data
for {
sym <- qualIdentNode(a, data.sym)
- } yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(sym = sym)
- )
- )
+ } yield {
+ val dataCopy = data.copy(sym = sym)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defModuleTemplateAnnotatedNode(
a: In,
@@ -897,14 +885,11 @@ object ExpandTemplates extends AstTransformer
members <- transformFlatList(a, data.members, matchModuleMember)
a <- Right(a.copy(templateDefId = None))
}
- yield (
- (),
- cloneAnnotatedNode(
- a,
- aNode,
- data.copy(params = params, members = members)
- )
- )
+ yield {
+ val dataCopy = data.copy(params = params, members = members)
+ val node = cloneAnnotatedNode(a, aNode, dataCopy)
+ ((), node)
+ }
override def defModuleAnnotatedNode(
a: Analysis,
@@ -966,14 +951,11 @@ object ExpandTemplates extends AstTransformer
): AstNode[Ast.QualIdent] = {
node.data match {
case Ast.QualIdent.Qualified(qualifier, name) =>
- cloneNode(
- a,
- node,
- Ast.QualIdent.Qualified(
- cloneQualIdentNode(a, qualifier),
- cloneNode(a, name, name.data)
- )
+ val qualIdent = Ast.QualIdent.Qualified(
+ cloneQualIdentNode(a, qualifier),
+ cloneNode(a, name, name.data)
)
+ cloneNode(a, node, qualIdent)
case Ast.QualIdent.Unqualified(name, isAbsolute) =>
cloneNode(a, node, Ast.QualIdent.Unqualified(name, isAbsolute))
}
From 3431b941e97e5c95eeeb23d22df6e03f4096345d Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 08:20:44 -0700
Subject: [PATCH 27/51] Refactor ExpandTemplates
---
.../src/main/scala/transform/ExpandTemplates.scala | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 4ae251685..dc2966383 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -60,15 +60,9 @@ object ExpandTemplates extends AstTransformer
a: In,
aNode: Ast.Annotated[AstNode[T]]
) = {
- a.templateExpansionId match {
- // We are not currently in a template expansion.
- // Leave the node alone.
- case None => Right((), aNode)
- case Some(_) =>
- val (pre, node, post) = aNode
- for ((_, inter) <- defaultNode(a, node))
- yield ((), (pre, inter, post))
- }
+ val (pre, node, post) = aNode
+ val node1 = cloneNode(a, node, node.data)
+ Right((), (pre, node1, post))
}
override def exprArrayNode(
From 44839b050507b13b48cddd75032aed627c65ab3a Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 08:31:31 -0700
Subject: [PATCH 28/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 35 +++++++++----------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index dc2966383..d88742b0e 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -1042,14 +1042,13 @@ object ExpandTemplates extends AstTransformer
for {
interfaceInstance <- qualIdentNode(a, pii.data.interfaceInstance)
(_, portName) <- defaultNode(a, pii.data.portName)
- } yield cloneNode(
- a,
- pii,
- pii.data.copy(
+ } yield {
+ val dataCopy = pii.data.copy(
interfaceInstance = interfaceInstance,
portName = portName
)
- )
+ cloneNode(a, pii, dataCopy)
+ }
}
private def qualIdentNode(
@@ -1094,15 +1093,14 @@ object ExpandTemplates extends AstTransformer
for {
size <- exprNodeOpt(a, data.size)
(_, typeName) <- matchTypeName(a, data.typeName)
- } yield cloneAnnotatedNode(
- a,
- aNode,
- data.copy(
- size = size,
- typeName = typeName,
- format = cloneStringNodeOpt(a, data.format)
- )
- )
+ } yield {
+ val dataCopy = data.copy(
+ size = size,
+ typeName = typeName,
+ format = cloneStringNodeOpt(a, data.format)
+ )
+ cloneAnnotatedNode(a, aNode, dataCopy)
+ }
private def transitionExpr(
a: In,
@@ -1111,11 +1109,10 @@ object ExpandTemplates extends AstTransformer
for {
actions <- transformList(a, node.data.actions, defaultNode)
target <- qualIdentNode(a, node.data.target)
- } yield cloneNode(
- a,
- node,
- node.data.copy(actions = actions, target = target)
- )
+ } yield {
+ val dataCopy = node.data.copy(actions = actions, target = target)
+ cloneNode(a, node, dataCopy)
+ }
private def transitionOrDo(
a: In,
From c59d1b540acb759ce2d60250a34f87f01786dafc Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 08:37:17 -0700
Subject: [PATCH 29/51] Refactor ExpandTemplates
---
compiler/lib/src/main/scala/transform/ExpandTemplates.scala | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index d88742b0e..57c2adb6d 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -1006,7 +1006,9 @@ object ExpandTemplates extends AstTransformer
)
} yield {
// Paste the expanded template body into the expansion specifier
- (pre, AstNode.create(data.copy(members = Some(members)), node.id), post)
+ val dataCopy = data.copy(members = Some(members))
+ val nodeCopy = AstNode.create(dataCopy, node.id)
+ (pre, nodeCopy, post)
}
}
From 40c439dd4049405acd5986ea84f6c2ab8e1e69ba Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 08:45:21 -0700
Subject: [PATCH 30/51] Refactor ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 148 +++++++++---------
1 file changed, 74 insertions(+), 74 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 57c2adb6d..5a9e2904f 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -57,7 +57,7 @@ object ExpandTemplates extends AstTransformer
) = Right((), cloneNode(a, node, node.data))
override def defaultAnnotatedNode[T](
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[T]]
) = {
val (pre, node, post) = aNode
@@ -66,7 +66,7 @@ object ExpandTemplates extends AstTransformer
}
override def exprArrayNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.Expr],
e: Ast.ExprArray
) =
@@ -74,7 +74,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneNode(a, node, Ast.ExprArray(result)))
override def exprArraySubscriptNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.Expr],
e: Ast.ExprArraySubscript
) =
@@ -85,7 +85,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneNode(a, node, Ast.ExprArraySubscript(e1, e2)))
override def exprBinopNode(
- a: In, node: AstNode[Ast.Expr],
+ a: Analysis, node: AstNode[Ast.Expr],
e: Ast.ExprBinop
) =
for {
@@ -95,15 +95,15 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneNode(a, node, Ast.ExprBinop(e1, e.op, e2)))
override def exprDotNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.Expr],
e: Ast.ExprDot
- ) =
+ ) =
for ((_, left) <- matchExprNode(a, e.e))
yield ((), cloneNode(a, node, Ast.ExprDot(left, cloneNode(a, e.id, e.id.data))))
override def exprParenNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.Expr],
e: Ast.ExprParen
) =
@@ -119,7 +119,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneNode(a, node, Ast.ExprStruct(result)))
override def exprUnopNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.Expr],
e: Ast.ExprUnop
) =
@@ -127,7 +127,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneNode(a, node, Ast.ExprUnop(e.op, ec)))
override def exprSizeOfNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.Expr],
e: Ast.ExprSizeOf
) =
@@ -135,7 +135,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneNode(a, node, Ast.ExprSizeOf(result)))
override def typeNameQualIdentNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.TypeName],
tn: Ast.TypeNameQualIdent
) = {
@@ -144,7 +144,7 @@ object ExpandTemplates extends AstTransformer
}
override def typeNameStringNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.TypeName],
tn: Ast.TypeNameString
) =
@@ -157,7 +157,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneNode(a, node, Ast.TypeNameString(valueOpt)))
override def defAliasTypeAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
): ResultAnnotatedNode[Ast.DefAliasType] =
val data = aNode._2.data
@@ -165,7 +165,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = ty)))
override def defArrayAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefArray]]
) = {
val data = aNode._2.data
@@ -186,7 +186,7 @@ object ExpandTemplates extends AstTransformer
}
override def defComponentAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefComponent]]
) = {
val data = aNode._2.data
@@ -195,7 +195,7 @@ object ExpandTemplates extends AstTransformer
}
override def defComponentInstanceAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefComponentInstance]]
) = {
val data = aNode._2.data
@@ -225,7 +225,7 @@ object ExpandTemplates extends AstTransformer
}
override def defInterfaceAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefInterface]]
) = {
val data = aNode._2.data
@@ -234,7 +234,7 @@ object ExpandTemplates extends AstTransformer
}
override def defConstantAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefConstant]]
) =
val data = aNode._2.data
@@ -246,7 +246,7 @@ object ExpandTemplates extends AstTransformer
}
override def defEnumAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefEnum]]
) =
val data = aNode._2.data
@@ -269,7 +269,7 @@ object ExpandTemplates extends AstTransformer
}
override def defPortAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefPort]]
) =
val data = aNode._2.data
@@ -289,7 +289,7 @@ object ExpandTemplates extends AstTransformer
defaultAnnotatedNode(in, node)
override def defStateMachineAnnotatedNodeInternal(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefStateMachine]],
members: List[Ast.StateMachineMember]
) =
@@ -298,7 +298,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = Some(members))))
override def defStateMachineAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefStateMachine]]
) =
val data = aNode._2.data
@@ -308,7 +308,7 @@ object ExpandTemplates extends AstTransformer
}
override def defActionAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefAction]]
) =
val data = aNode._2.data
@@ -317,7 +317,7 @@ object ExpandTemplates extends AstTransformer
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
override def defChoiceAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefChoice]]
) =
val data = aNode._2.data
@@ -336,7 +336,7 @@ object ExpandTemplates extends AstTransformer
}
override def defGuardAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefGuard]]
) =
val data = aNode._2.data
@@ -344,7 +344,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
override def defSignalAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefSignal]]
) =
val data = aNode._2.data
@@ -352,7 +352,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(typeName = typeName)))
override def defStateAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefState]]
) =
val data = aNode._2.data
@@ -360,7 +360,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(members = members)))
override def specInitialTransitionAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecInitialTransition]]
) =
val data = aNode._2.data
@@ -368,7 +368,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(transition = transition)))
override def specStateEntryAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecStateEntry]]
) =
val data = aNode._2.data
@@ -376,7 +376,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
override def specStateExitAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecStateExit]]
) =
val data = aNode._2.data
@@ -384,7 +384,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(actions = actions)))
override def specStateTransitionAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecStateTransition]]
) =
val data = aNode._2.data
@@ -403,7 +403,7 @@ object ExpandTemplates extends AstTransformer
}
override def defStructAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefStruct]]
) =
val data = aNode._2.data
@@ -417,7 +417,7 @@ object ExpandTemplates extends AstTransformer
}
override def defTopologyAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefTopology]]
) =
val data = aNode._2.data
@@ -431,7 +431,7 @@ object ExpandTemplates extends AstTransformer
}
override def defSystemAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefSystem]]
) =
val data = aNode._2.data
@@ -443,7 +443,7 @@ object ExpandTemplates extends AstTransformer
}
override def specCommandAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecCommand]]
) =
val data = aNode._2.data
@@ -464,7 +464,7 @@ object ExpandTemplates extends AstTransformer
}
override def specInstanceAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecInstance]]
) =
val data = aNode._2.data
@@ -477,13 +477,13 @@ object ExpandTemplates extends AstTransformer
}
override def specConnectionGraphAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecConnectionGraph]]
) = {
val data = aNode._2.data
def connection(
- a: In,
+ a: Analysis,
connection: Ast.SpecConnectionGraph.Connection
): Result[Ast.SpecConnectionGraph.Connection] = {
for {
@@ -524,7 +524,7 @@ object ExpandTemplates extends AstTransformer
}
override def specContainerAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecContainer]]
) =
val data = aNode._2.data
@@ -538,7 +538,7 @@ object ExpandTemplates extends AstTransformer
}
override def specEventAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecEvent]]
) =
val data = aNode._2.data
@@ -570,7 +570,7 @@ object ExpandTemplates extends AstTransformer
}
override def specIncludeAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecInclude]]
) =
val data = aNode._2.data
@@ -579,7 +579,7 @@ object ExpandTemplates extends AstTransformer
} yield ((), cloneAnnotatedNode(a, aNode, data.copy(file = file)))
override def specInitAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecInit]]
) =
val data = aNode._2.data
@@ -587,7 +587,7 @@ object ExpandTemplates extends AstTransformer
yield ((), cloneAnnotatedNode(a, aNode, data.copy(phase=phase)))
override def specInternalPortAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecInternalPort]]
) =
val data = aNode._2.data
@@ -601,7 +601,7 @@ object ExpandTemplates extends AstTransformer
}
override def specLocAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecLoc]]
) =
val data = aNode._2.data
@@ -615,7 +615,7 @@ object ExpandTemplates extends AstTransformer
}
override def specParamAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecParam]]
) =
val data = aNode._2.data
@@ -638,7 +638,7 @@ object ExpandTemplates extends AstTransformer
}
override def specPortInstanceAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecPortInstance]]
) =
val data = aNode._2.data
@@ -671,7 +671,7 @@ object ExpandTemplates extends AstTransformer
}
override def specPortMatchingAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecPortMatching]]
) =
val data = aNode._2.data
@@ -685,7 +685,7 @@ object ExpandTemplates extends AstTransformer
}
override def specRecordAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecRecord]]
) =
val data = aNode._2.data
@@ -699,7 +699,7 @@ object ExpandTemplates extends AstTransformer
}
override def specStateMachineInstanceAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecStateMachineInstance]]
) =
val data = aNode._2.data
@@ -713,12 +713,12 @@ object ExpandTemplates extends AstTransformer
}
override def specTlmChannelAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTlmChannel]]
) =
val data = aNode._2.data
def limit(
- a: In,
+ a: Analysis,
limit: Ast.SpecTlmChannel.Limit
): Result[Ast.SpecTlmChannel.Limit] = {
val (kind, value) = limit
@@ -746,12 +746,12 @@ object ExpandTemplates extends AstTransformer
}
override def specTlmPacketAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTlmPacket]]
) =
val data = aNode._2.data
def tlmPacketMember(
- a: In,
+ a: Analysis,
member: Ast.TlmPacketMember
): Result[Ast.TlmPacketMember] = {
member match {
@@ -793,7 +793,7 @@ object ExpandTemplates extends AstTransformer
}
override def specTopPortAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTopPort]]
) =
val data = aNode._2.data
@@ -805,12 +805,12 @@ object ExpandTemplates extends AstTransformer
}
override def specTlmPacketSetAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecTlmPacketSet]]
) =
val data = aNode._2.data
def tlmChannelIdentifier(
- a: In,
+ a: Analysis,
node: AstNode[Ast.TlmChannelIdentifier]
): ResultNode[Ast.TlmChannelIdentifier] =
val data = node.data
@@ -836,7 +836,7 @@ object ExpandTemplates extends AstTransformer
}
override def specInterfaceImportAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.SpecImport]]
) =
val data = aNode._2.data
@@ -849,14 +849,14 @@ object ExpandTemplates extends AstTransformer
}
override def defModuleTemplateAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefModuleTemplate]]
) =
val (_, node, _) = aNode
val data = node.data
def templateParam(
- a: In,
+ a: Analysis,
param: Ast.Annotated[AstNode[Ast.TemplateParam]]
): ResultAnnotatedNode[Ast.TemplateParam] = {
val (_, node, _) = param
@@ -903,7 +903,7 @@ object ExpandTemplates extends AstTransformer
val data = node.data
data.members match {
// Members are already there; nothing to do
- case Some(members) => Right((), aNode)
+ case Some(members) => Right((), aNode)
// Members are not there; expand
case None => (resultAdapter(expandTemplate))(a, aNode)
}
@@ -940,7 +940,7 @@ object ExpandTemplates extends AstTransformer
}
private def cloneQualIdentNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.QualIdent]
): AstNode[Ast.QualIdent] = {
node.data match {
@@ -956,7 +956,7 @@ object ExpandTemplates extends AstTransformer
}
private def cloneStringNodeOpt(
- a: In,
+ a: Analysis,
node: Option[AstNode[String]]
): Option[AstNode[String]] =
node match {
@@ -976,7 +976,7 @@ object ExpandTemplates extends AstTransformer
}
private def defEnumConstantAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefEnumConstant]]
): Result.Result[Ast.Annotated[AstNode[Ast.DefEnumConstant]]] =
val data = aNode._2.data
@@ -993,7 +993,7 @@ object ExpandTemplates extends AstTransformer
for {
// Look up the template def
tmpl <- a.getTemplateSymbol(data.template.id)
- // Clone the template body, recording the expansion node so that
+ // Clone the template body, recording the expansion node so that
// cloned nodes point back at the expansion site.
// Record the template definition too for diagnostics.
members <- transformFlatList(
@@ -1013,7 +1013,7 @@ object ExpandTemplates extends AstTransformer
}
private def exprNodeOpt(
- a: In,
+ a: Analysis,
node: Option[AstNode[Ast.Expr]]
): Result.Result[Option[AstNode[Ast.Expr]]] =
node match {
@@ -1024,7 +1024,7 @@ object ExpandTemplates extends AstTransformer
}
private def formalAnnotatatedParam(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.FormalParam]]
) =
val data = aNode._2.data
@@ -1032,13 +1032,13 @@ object ExpandTemplates extends AstTransformer
yield cloneAnnotatedNode(a, aNode, data.copy(typeName = ty))
private def formalParamList(
- a: In,
+ a: Analysis,
aNode: Ast.FormalParamList
) = for (node <- transformList(a, aNode, resultAdapter(formalAnnotatatedParam)))
yield node
private def portInstanceIdentifierNode(
- a: In,
+ a: Analysis,
pii: AstNode[Ast.PortInstanceIdentifier]
): Result.Result[AstNode[Ast.PortInstanceIdentifier]] = {
for {
@@ -1054,13 +1054,13 @@ object ExpandTemplates extends AstTransformer
}
private def qualIdentNode(
- a: In,
+ a: Analysis,
node: AstNode[Ast.QualIdent]
): Result.Result[AstNode[Ast.QualIdent]] =
Right(cloneQualIdentNode(a, node))
private def qualIdentNodeOpt(
- a: In,
+ a: Analysis,
qi: Option[AstNode[Ast.QualIdent]]
): Result.Result[Option[AstNode[Ast.QualIdent]]] = {
qi match {
@@ -1088,7 +1088,7 @@ object ExpandTemplates extends AstTransformer
}
private def structTypeMemberAnnotatedNode(
- a: In,
+ a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.StructTypeMember]]
) =
val data = aNode._2.data
@@ -1105,7 +1105,7 @@ object ExpandTemplates extends AstTransformer
}
private def transitionExpr(
- a: In,
+ a: Analysis,
node: AstNode[Ast.TransitionExpr]
): Result.Result[AstNode[Ast.TransitionExpr]] =
for {
@@ -1117,7 +1117,7 @@ object ExpandTemplates extends AstTransformer
}
private def transitionOrDo(
- a: In,
+ a: Analysis,
transitionOrDo: Ast.TransitionOrDo
) =
transitionOrDo match
@@ -1127,9 +1127,9 @@ object ExpandTemplates extends AstTransformer
case Ast.TransitionOrDo.Do(actions) =>
for (result <- transformList(a, actions, defaultNode))
yield Ast.TransitionOrDo.Do(result)
-
+
private def typeNameNodeOpt(
- a: In,
+ a: Analysis,
node: Option[AstNode[Ast.TypeName]]
): Result.Result[Option[AstNode[Ast.TypeName]]] =
node match {
From 06f86b0871fab480c60fcde9e4a536f2b18a67c3 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 08:56:22 -0700
Subject: [PATCH 31/51] Refactor analysis
---
.../scala/analysis/CheckSemantics/CheckTemplateDefs.scala | 2 +-
.../lib/src/main/scala/transform/ExpandTemplates.scala | 7 +++----
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
index 61a92d176..09777f515 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
@@ -24,7 +24,7 @@ object CheckTemplateDefs
Locations.get(defId)
)
)
- case None => Right(a)
+ case None => Right(())
}
a <- Right(a.copy(templateDefId = Some(node.id)))
a <- visitList(a, data.members, matchModuleMember)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 5a9e2904f..5a06ebc8f 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -874,10 +874,9 @@ object ExpandTemplates extends AstTransformer
}
for {
- a <- Right(a.copy(templateDefId = Some(node.id)))
- params <- transformList(a, data.params, templateParam)
- members <- transformFlatList(a, data.members, matchModuleMember)
- a <- Right(a.copy(templateDefId = None))
+ a1 <- Right(a.copy(templateDefId = Some(node.id)))
+ params <- transformList(a1, data.params, templateParam)
+ members <- transformFlatList(a1, data.members, matchModuleMember)
}
yield {
val dataCopy = data.copy(params = params, members = members)
From 1f16a9e69f2b1e21aa432036fe79678a4e92ad0b Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 09:04:02 -0700
Subject: [PATCH 32/51] Add outline of CheckTemplateExpansions
---
.../CheckTemplateExpansions.scala | 22 +++++++++++++++++++
.../ExpandSyntaxAndEnterSymbols.scala | 2 +-
compiler/lib/src/main/scala/util/Error.scala | 16 +++++++++++++-
3 files changed, 38 insertions(+), 2 deletions(-)
create mode 100644 compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala
new file mode 100644
index 000000000..646f49ac0
--- /dev/null
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala
@@ -0,0 +1,22 @@
+package fpp.compiler.analysis
+
+import fpp.compiler.ast._
+import fpp.compiler.util._
+
+/** Check template expansions */
+object CheckTemplateExpansions
+ extends Analyzer
+ with ModuleAnalyzer
+{
+
+ override def defModuleTemplateAnnotatedNode(
+ a: Analysis,
+ aNode: Ast.Annotated[AstNode[Ast.DefModuleTemplate]]
+ ) = Right(a)
+
+ override def specTemplateExpandAnnotatedNode(
+ a: Analysis,
+ aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
+ ) = Right(a)
+
+}
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
index 2df372f13..5fe3c2f5a 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
@@ -17,7 +17,7 @@ object ExpandSyntaxAndEnterSymbols {
tul <- AddStateEnums.transUnitList(tul)
a <- EnterSymbols.visitList(a, tul, EnterSymbols.transUnit)
a <- CheckTemplateDefs.visitList(a, tul, CheckTemplateDefs.transUnit)
- // TODO: CheckTemplateExpansions
+ a <- CheckTemplateExpansions.visitList(a, tul, CheckTemplateExpansions.transUnit)
a <- CheckTemplateUses.visitList(a, tul, CheckTemplateUses.transUnit)
tul <- ExpandTemplates.transformList(a, tul, ExpandTemplates.transUnit)
a <- EnterTemplateExpansionSymbols.visitList(a, tul, EnterTemplateExpansionSymbols.transUnit)
diff --git a/compiler/lib/src/main/scala/util/Error.scala b/compiler/lib/src/main/scala/util/Error.scala
index f17f1e8bb..01f2858e3 100644
--- a/compiler/lib/src/main/scala/util/Error.scala
+++ b/compiler/lib/src/main/scala/util/Error.scala
@@ -387,10 +387,18 @@ sealed trait Error {
loc: Location,
msg: String,
defLoc: Location
- ) =>
+ ) =>
Error.print (Some(loc)) (msg)
System.err.println("enclosing template is defined here:")
System.err.println(defLoc)
+ case SemanticError.TemplateExpandError(
+ loc: Location,
+ msg: String,
+ expandLoc: Location
+ ) =>
+ Error.print (Some(loc)) (msg)
+ System.err.println("enclosing template expansion is here:")
+ System.err.println(expandLoc)
case SemanticError.TooManyOutputPorts(loc, numPorts, arraySize, instanceLoc) =>
Error.print (Some(loc)) (s"too many ports connected here (found $numPorts, max is $arraySize)")
System.err.println("for this component instance:")
@@ -883,6 +891,12 @@ object SemanticError {
msg: String,
defLoc: Location
) extends Error
+ /** Error in template expansion */
+ final case class TemplateExpandError(
+ loc: Location,
+ msg: String,
+ expandLoc: Location
+ ) extends Error
/** Template parameter conflicts with a definition in the template body */
final case class TemplateParameterConflict(
paramName: String,
From 9e01546855b47b60d80cd25b459c88704aca5dce Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 09:37:31 -0700
Subject: [PATCH 33/51] Revise CheckTemplateExpansions
---
.../CheckTemplateExpansions.scala | 40 +++++++++++++++++--
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala
index 646f49ac0..132bc4fad 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateExpansions.scala
@@ -12,11 +12,43 @@ object CheckTemplateExpansions
override def defModuleTemplateAnnotatedNode(
a: Analysis,
aNode: Ast.Annotated[AstNode[Ast.DefModuleTemplate]]
- ) = Right(a)
+ ) =
+ a.templateExpansionId match {
+ case Some(expandId) => Left(
+ SemanticError.TemplateExpandError(
+ Locations.get(aNode._2.id),
+ "module template definitions cannot appear inside a template expansion",
+ Locations.get(expandId)
+ )
+ )
+ case None => Right(a)
+ }
- override def specTemplateExpandAnnotatedNode(
+ override def specTemplateExpandAnnotatedNodeExpanded(
a: Analysis,
- aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
- ) = Right(a)
+ aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]],
+ members: List[Ast.ModuleMember]
+ ) =
+ for {
+ a <- specTemplateExpandAnnotatedNodeUnexpanded(a, aNode)
+ a <- Right(a.copy(templateExpansionId = Some(aNode._2.id)))
+ a <- visitList(a, members, matchModuleMember)
+ a <- Right(a.copy(templateExpansionId = None))
+ } yield a
+
+ override def specTemplateExpandAnnotatedNodeUnexpanded(
+ a: Analysis,
+ aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]],
+ ) =
+ a.templateExpansionId match {
+ case Some(defId) => Left(
+ SemanticError.TemplateExpandError(
+ Locations.get(aNode._2.id),
+ "template expansions cannot be nested",
+ Locations.get(defId)
+ )
+ )
+ case None => Right(a)
+ }
}
From 672eb469fb57edcf4848727da0e39351df28919e Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 09:45:49 -0700
Subject: [PATCH 34/51] Rename Expand Syntax
To conform to the style of the other analysis passes
---
docs/wiki/Checking-Semantics.asciidoc | 2 +-
...ymbols.asciidoc => Expand-Syntax-and-Enter-Symbols.asciidoc} | 0
docs/wiki/fpp-filenames.asciidoc | 2 +-
docs/wiki/fpp-locate-defs.asciidoc | 2 +-
docs/wiki/fpp-syntax.asciidoc | 2 +-
docs/wiki/fpp-to-fpp.asciidoc | 2 +-
6 files changed, 5 insertions(+), 5 deletions(-)
rename docs/wiki/{Expanding-Syntax-and-Entering-Symbols.asciidoc => Expand-Syntax-and-Enter-Symbols.asciidoc} (100%)
diff --git a/docs/wiki/Checking-Semantics.asciidoc b/docs/wiki/Checking-Semantics.asciidoc
index a0331d10b..43a56dc1e 100644
--- a/docs/wiki/Checking-Semantics.asciidoc
+++ b/docs/wiki/Checking-Semantics.asciidoc
@@ -16,7 +16,7 @@ the results of syntax expansion.
== Procedure
-. https://github.com/nasa/fpp/wiki/Expanding-Syntax-and-Entering-Symbols[Expand syntax and enter symbols]
+. https://github.com/nasa/fpp/wiki/Expand-Syntax-and-Enter-Symbols[Expand syntax and enter symbols]
for _a_ and _tul_.
. https://github.com/nasa/fpp/wiki/Construct-Implied-Use-Map[Construct the implied use map] for _a_ and _tul_.
diff --git a/docs/wiki/Expanding-Syntax-and-Entering-Symbols.asciidoc b/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
similarity index 100%
rename from docs/wiki/Expanding-Syntax-and-Entering-Symbols.asciidoc
rename to docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
diff --git a/docs/wiki/fpp-filenames.asciidoc b/docs/wiki/fpp-filenames.asciidoc
index 731b26fbc..18fe46394 100644
--- a/docs/wiki/fpp-filenames.asciidoc
+++ b/docs/wiki/fpp-filenames.asciidoc
@@ -28,7 +28,7 @@ by running `fpp-to-cpp` with the corresponding options.
. Parse each of the files in _fl_, generating a list _tul_ of translation units.
. Run the first three steps of
-https://github.com/nasa/fpp/wiki/Expanding-Syntax-and-Entering-Symbols[expanding
+https://github.com/nasa/fpp/wiki/Expand-Syntax-and-Enter-Symbols[expanding
syntax and entering symbols] (up to template resolution) on _tul_.
. Walk the AST and identify the definitions that cause C++ or JSON files to
diff --git a/docs/wiki/fpp-locate-defs.asciidoc b/docs/wiki/fpp-locate-defs.asciidoc
index 2c29049f5..4823964d3 100644
--- a/docs/wiki/fpp-locate-defs.asciidoc
+++ b/docs/wiki/fpp-locate-defs.asciidoc
@@ -34,7 +34,7 @@ symbol defined in _fl_.
. Parse each of the files in _fl_, generating a list _tul_ of translation units.
-. https://github.com/nasa/fpp/wiki/Expanding-Syntax-and-Entering-Symbols[Expand
+. https://github.com/nasa/fpp/wiki/Expand-Syntax-and-Enter-Symbols[Expand
syntax and enter symbols] for _tul_.
. For each definition _d_ appearing in _tul_ write out a location specifier
diff --git a/docs/wiki/fpp-syntax.asciidoc b/docs/wiki/fpp-syntax.asciidoc
index 2d58602a4..ec9345ffa 100644
--- a/docs/wiki/fpp-syntax.asciidoc
+++ b/docs/wiki/fpp-syntax.asciidoc
@@ -33,7 +33,7 @@ the individual ASTs.
message.
. If `-e` is present, then
-https://github.com/nasa/fpp/wiki/Expanding-Syntax-and-Entering-Symbols[expand
+https://github.com/nasa/fpp/wiki/Expand-Syntax-and-Enter-Symbols[expand
syntax and enter symbols],
yielding a new list _tul'_ of translation units.
diff --git a/docs/wiki/fpp-to-fpp.asciidoc b/docs/wiki/fpp-to-fpp.asciidoc
index ae0ce4aba..e31db929f 100644
--- a/docs/wiki/fpp-to-fpp.asciidoc
+++ b/docs/wiki/fpp-to-fpp.asciidoc
@@ -44,7 +44,7 @@ errors that occur.
include cycles. Upon detecting an include cycle, halt with an error message.
. If `-e` is present, then
-https://github.com/nasa/fpp/wiki/Expanding-Syntax-and-Entering-Symbols[expand
+https://github.com/nasa/fpp/wiki/Expand-Syntax-and-Enter-Symbols[expand
syntax and enter symbols].
. Write out the formatted source code.
From 50f1f0f433863f77bb0593167545ba44e8696905 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 10:01:22 -0700
Subject: [PATCH 35/51] Revise ExpandSyntax
Add CheckTemplateDefinitions
---
...s.scala => CheckTemplateDefinitions.scala} | 2 +-
.../ExpandSyntaxAndEnterSymbols.scala | 2 +-
docs/wiki/Check-Template-Definitions.asciidoc | 27 +++++++++++++++++++
.../Expand-Syntax-and-Enter-Symbols.asciidoc | 5 ++++
4 files changed, 34 insertions(+), 2 deletions(-)
rename compiler/lib/src/main/scala/analysis/CheckSemantics/{CheckTemplateDefs.scala => CheckTemplateDefinitions.scala} (97%)
create mode 100644 docs/wiki/Check-Template-Definitions.asciidoc
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefinitions.scala
similarity index 97%
rename from compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
rename to compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefinitions.scala
index 09777f515..e11bcbf20 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefinitions.scala
@@ -4,7 +4,7 @@ import fpp.compiler.ast._
import fpp.compiler.util._
/** Check template definitions */
-object CheckTemplateDefs
+object CheckTemplateDefinitions
extends Analyzer
with ModuleAnalyzer
{
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
index 5fe3c2f5a..a8cc751ce 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
@@ -16,7 +16,7 @@ object ExpandSyntaxAndEnterSymbols {
(a, tul) <- ResolveSpecInclude.transUnitList(a, tul)
tul <- AddStateEnums.transUnitList(tul)
a <- EnterSymbols.visitList(a, tul, EnterSymbols.transUnit)
- a <- CheckTemplateDefs.visitList(a, tul, CheckTemplateDefs.transUnit)
+ a <- CheckTemplateDefinitions.visitList(a, tul, CheckTemplateDefinitions.transUnit)
a <- CheckTemplateExpansions.visitList(a, tul, CheckTemplateExpansions.transUnit)
a <- CheckTemplateUses.visitList(a, tul, CheckTemplateUses.transUnit)
tul <- ExpandTemplates.transformList(a, tul, ExpandTemplates.transUnit)
diff --git a/docs/wiki/Check-Template-Definitions.asciidoc b/docs/wiki/Check-Template-Definitions.asciidoc
new file mode 100644
index 000000000..49bd0807f
--- /dev/null
+++ b/docs/wiki/Check-Template-Definitions.asciidoc
@@ -0,0 +1,27 @@
+This algorithm traverses a source model and checks template
+definitions for correctness.
+
+== Input
+
+. A list _tul_ of translation units.
+
+. An
+https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[analysis
+data structure] _a_
+representing the results of analysis so far.
+
+== Output
+
+. None if the check passes; otherwise an error.
+
+== Procedure
+
+Currently this analysis does the following:
+
+. Check that no template definition transitively contains a template definition.
+
+. Check that no template definition transitively contains a template expansion.
+
+Eventually we will implement all of the checking described in the
+https://nasa.github.io/fpp/fpp-spec.html#Definitions_Module-Template-Definitions_Semantics[FPP
+specification].
diff --git a/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc b/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
index 4a9307bba..3569e967b 100644
--- a/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
+++ b/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
@@ -37,6 +37,11 @@ machine definition that has a body has a state enum definition.
. https://github.com/nasa/fpp/wiki/Enter-Symbols[Enter symbols] for _a_ and _tul_.
+. https://github.com/nasa/fpp/wiki/Check-Template-Definitions[Check template
+ definitions] for _a_ and _tul_.
+
+. TODO: Check template expansions
+
. https://github.com/nasa/fpp/wiki/Check-Template-Uses[Check template uses] for _a_ and _tul_.
. https://github.com/nasa/fpp/wiki/Expand-Templates[Expand templates] for _a_ and _tul_,
From 0c95945557029785011449a730db210c91a68411 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 10:15:36 -0700
Subject: [PATCH 36/51] Revise ExpandSyntax
---
docs/wiki/Check-Template-Expansions.asciidoc | 23 +++++++++++++++++++
.../Expand-Syntax-and-Enter-Symbols.asciidoc | 3 ++-
2 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 docs/wiki/Check-Template-Expansions.asciidoc
diff --git a/docs/wiki/Check-Template-Expansions.asciidoc b/docs/wiki/Check-Template-Expansions.asciidoc
new file mode 100644
index 000000000..c92e01ae1
--- /dev/null
+++ b/docs/wiki/Check-Template-Expansions.asciidoc
@@ -0,0 +1,23 @@
+This algorithm traverses a source model and checks template
+expansions for correctness.
+This check covers only pre-expanded `expand` specifiers, i.e.,
+expand specifiers written in the form `expand T { ... }`.
+
+== Input
+
+. A list _tul_ of translation units.
+
+. An
+https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[analysis
+data structure] _a_
+representing the results of analysis so far.
+
+== Output
+
+. None if the check passes; otherwise an error.
+
+== Procedure
+
+. Check that no template expansion transitively contains a template definition.
+
+. Check that no template expansion transitively contains a template expansion.
diff --git a/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc b/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
index 3569e967b..aab8921bc 100644
--- a/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
+++ b/docs/wiki/Expand-Syntax-and-Enter-Symbols.asciidoc
@@ -40,7 +40,8 @@ machine definition that has a body has a state enum definition.
. https://github.com/nasa/fpp/wiki/Check-Template-Definitions[Check template
definitions] for _a_ and _tul_.
-. TODO: Check template expansions
+. https://github.com/nasa/fpp/wiki/Check-Template-Expansions[Check template
+ expansions] for _a_ and _tul_.
. https://github.com/nasa/fpp/wiki/Check-Template-Uses[Check template uses] for _a_ and _tul_.
From faaab98cbaf652640c63d829d388a392c14da6c5 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 11:17:52 -0700
Subject: [PATCH 37/51] Revise fpp-check tests
---
.../test/template/composition_invalid.fpp | 11 ----------
.../test/template/composition_invalid.ref.txt | 9 --------
.../test/template/expand_in_template_def.fpp | 9 ++++++++
.../template/expand_in_template_def.ref.txt | 9 ++++++++
.../test/template/invalid_nested.fpp | 22 -------------------
.../test/template/invalid_nested.ref.txt | 9 --------
.../test/template/nested_template_def.fpp | 7 ++++++
.../test/template/nested_template_def.ref.txt | 9 ++++++++
.../tools/fpp-check/test/template/tests.sh | 4 ++--
9 files changed, 36 insertions(+), 53 deletions(-)
delete mode 100644 compiler/tools/fpp-check/test/template/composition_invalid.fpp
delete mode 100644 compiler/tools/fpp-check/test/template/composition_invalid.ref.txt
create mode 100644 compiler/tools/fpp-check/test/template/expand_in_template_def.fpp
create mode 100644 compiler/tools/fpp-check/test/template/expand_in_template_def.ref.txt
delete mode 100644 compiler/tools/fpp-check/test/template/invalid_nested.fpp
delete mode 100644 compiler/tools/fpp-check/test/template/invalid_nested.ref.txt
create mode 100644 compiler/tools/fpp-check/test/template/nested_template_def.fpp
create mode 100644 compiler/tools/fpp-check/test/template/nested_template_def.ref.txt
diff --git a/compiler/tools/fpp-check/test/template/composition_invalid.fpp b/compiler/tools/fpp-check/test/template/composition_invalid.fpp
deleted file mode 100644
index a5c9e08cd..000000000
--- a/compiler/tools/fpp-check/test/template/composition_invalid.fpp
+++ /dev/null
@@ -1,11 +0,0 @@
-module template T1(
- constant p: U32
-) {
- constant c = p
-}
-
-module template T2(
- constant p: U32
-) {
- expand T1(constant p)
-}
diff --git a/compiler/tools/fpp-check/test/template/composition_invalid.ref.txt b/compiler/tools/fpp-check/test/template/composition_invalid.ref.txt
deleted file mode 100644
index 9df63fadb..000000000
--- a/compiler/tools/fpp-check/test/template/composition_invalid.ref.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-fpp-check
-[ local path prefix ]/compiler/tools/fpp-check/test/template/composition_invalid.fpp:10.5
- expand T1(constant p)
- ^
-error: template expansion specifiers cannot appear inside a module template
-enclosing template is defined here:
-[ local path prefix ]/compiler/tools/fpp-check/test/template/composition_invalid.fpp:7.1
-module template T2(
-^
diff --git a/compiler/tools/fpp-check/test/template/expand_in_template_def.fpp b/compiler/tools/fpp-check/test/template/expand_in_template_def.fpp
new file mode 100644
index 000000000..54621c4d9
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/expand_in_template_def.fpp
@@ -0,0 +1,9 @@
+module template T1 {
+
+}
+
+module template T2 {
+
+ expand T1
+
+}
diff --git a/compiler/tools/fpp-check/test/template/expand_in_template_def.ref.txt b/compiler/tools/fpp-check/test/template/expand_in_template_def.ref.txt
new file mode 100644
index 000000000..469ffdc57
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/expand_in_template_def.ref.txt
@@ -0,0 +1,9 @@
+fpp-check
+[ local path prefix ]/compiler/tools/fpp-check/test/template/expand_in_template_def.fpp:7.3
+ expand T1
+ ^
+error: template expansion specifiers cannot appear inside a module template
+enclosing template is defined here:
+[ local path prefix ]/compiler/tools/fpp-check/test/template/expand_in_template_def.fpp:5.1
+module template T2 {
+^
diff --git a/compiler/tools/fpp-check/test/template/invalid_nested.fpp b/compiler/tools/fpp-check/test/template/invalid_nested.fpp
deleted file mode 100644
index e52774a66..000000000
--- a/compiler/tools/fpp-check/test/template/invalid_nested.fpp
+++ /dev/null
@@ -1,22 +0,0 @@
-module template Outer(constant c1: U32) {
- module template Inner(constant c2: U32) {
- constant k1 = c2 * 2
- }
-
- module M1 {
- expand Inner(constant 10)
- constant k2 = k1 * 3
- }
-
- module M2 {
- expand Inner(constant 20)
- constant k2 = k1 * 3
- }
-
- expand Inner(constant 30)
-
- constant j1 = M1.k1 + M2.k2
- constant j2 = k1 + M1.k1 + M2.k1
-}
-
-expand Outer(constant 10)
diff --git a/compiler/tools/fpp-check/test/template/invalid_nested.ref.txt b/compiler/tools/fpp-check/test/template/invalid_nested.ref.txt
deleted file mode 100644
index a20441bde..000000000
--- a/compiler/tools/fpp-check/test/template/invalid_nested.ref.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-fpp-check
-[ local path prefix ]/compiler/tools/fpp-check/test/template/invalid_nested.fpp:2.5
- module template Inner(constant c2: U32) {
- ^
-error: module template definitions cannot be nested
-enclosing template is defined here:
-[ local path prefix ]/compiler/tools/fpp-check/test/template/invalid_nested.fpp:1.1
-module template Outer(constant c1: U32) {
-^
diff --git a/compiler/tools/fpp-check/test/template/nested_template_def.fpp b/compiler/tools/fpp-check/test/template/nested_template_def.fpp
new file mode 100644
index 000000000..0b47b127c
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/nested_template_def.fpp
@@ -0,0 +1,7 @@
+module template T1 {
+
+ module template T2 {
+
+ }
+
+}
diff --git a/compiler/tools/fpp-check/test/template/nested_template_def.ref.txt b/compiler/tools/fpp-check/test/template/nested_template_def.ref.txt
new file mode 100644
index 000000000..f3c2f2542
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/nested_template_def.ref.txt
@@ -0,0 +1,9 @@
+fpp-check
+[ local path prefix ]/compiler/tools/fpp-check/test/template/nested_template_def.fpp:3.5
+ module template T2 {
+ ^
+error: module template definitions cannot be nested
+enclosing template is defined here:
+[ local path prefix ]/compiler/tools/fpp-check/test/template/nested_template_def.fpp:1.1
+module template T1 {
+^
diff --git a/compiler/tools/fpp-check/test/template/tests.sh b/compiler/tools/fpp-check/test/template/tests.sh
index 711ed0c51..8a84ef5c4 100644
--- a/compiler/tools/fpp-check/test/template/tests.sh
+++ b/compiler/tools/fpp-check/test/template/tests.sh
@@ -13,13 +13,13 @@ basic_constant
bound_param_capture
bound_param_capture_ok
chained_constants
-composition_invalid
constant_param_array_promote
constant_param_array_promote_bad_subscript
constant_with_default
definition_point_scoping
definition_point_scoping_ok
duplicate_def
+expand_in_template_def
import_two_expansions_ok
interfaces
interfaces_arg_bad_signature
@@ -35,10 +35,10 @@ interfaces_topology_arg_deployment
interfaces_topology_arg_ok
interfaces_topology_arg_order_ok
interfaces_valid_port_instance_name_aliased
-invalid_nested
module_merge_ok
nested_scope_resolution
nested_scope_resolution_ok
+nested_template_def
param_body_def_different_group_ok
param_conflict_body_def
param_conflict_same_name_group
From d673cac3d089e72a34022764c6b416d060da3625 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Tue, 13 Oct 2026 11:25:54 -0700
Subject: [PATCH 38/51] Revise fpp-check tests
---
.../tools/fpp-check/test/template/nested_expand.fpp | 9 +++++++++
.../fpp-check/test/template/nested_expand.ref.txt | 9 +++++++++
.../test/template/source_expand_bad_args.fpp | 9 +++++++++
.../test/template/source_expand_bad_args.ref.txt | 9 +++++++++
.../fpp-check/test/template/source_expand_ok.fpp | 9 +++++++++
.../fpp-check/test/template/source_expand_ok.ref.txt | 0
.../test/template/source_expand_undefined_symbol.fpp | 9 +++++++++
.../template/source_expand_undefined_symbol.ref.txt | 6 ++++++
.../test/template/template_def_in_expand.fpp | 11 +++++++++++
.../test/template/template_def_in_expand.ref.txt | 9 +++++++++
compiler/tools/fpp-check/test/template/tests.sh | 5 +++++
11 files changed, 85 insertions(+)
create mode 100644 compiler/tools/fpp-check/test/template/nested_expand.fpp
create mode 100644 compiler/tools/fpp-check/test/template/nested_expand.ref.txt
create mode 100644 compiler/tools/fpp-check/test/template/source_expand_bad_args.fpp
create mode 100644 compiler/tools/fpp-check/test/template/source_expand_bad_args.ref.txt
create mode 100644 compiler/tools/fpp-check/test/template/source_expand_ok.fpp
create mode 100644 compiler/tools/fpp-check/test/template/source_expand_ok.ref.txt
create mode 100644 compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.fpp
create mode 100644 compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.ref.txt
create mode 100644 compiler/tools/fpp-check/test/template/template_def_in_expand.fpp
create mode 100644 compiler/tools/fpp-check/test/template/template_def_in_expand.ref.txt
diff --git a/compiler/tools/fpp-check/test/template/nested_expand.fpp b/compiler/tools/fpp-check/test/template/nested_expand.fpp
new file mode 100644
index 000000000..a9e989c18
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/nested_expand.fpp
@@ -0,0 +1,9 @@
+module template T1 {
+
+}
+
+expand T1 {
+
+ expand T1
+
+}
diff --git a/compiler/tools/fpp-check/test/template/nested_expand.ref.txt b/compiler/tools/fpp-check/test/template/nested_expand.ref.txt
new file mode 100644
index 000000000..5db5a806b
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/nested_expand.ref.txt
@@ -0,0 +1,9 @@
+fpp-check
+[ local path prefix ]/compiler/tools/fpp-check/test/template/nested_expand.fpp:7.3
+ expand T1
+ ^
+error: template expansions cannot be nested
+enclosing template expansion is here:
+[ local path prefix ]/compiler/tools/fpp-check/test/template/nested_expand.fpp:5.1
+expand T1 {
+^
diff --git a/compiler/tools/fpp-check/test/template/source_expand_bad_args.fpp b/compiler/tools/fpp-check/test/template/source_expand_bad_args.fpp
new file mode 100644
index 000000000..796116e62
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/source_expand_bad_args.fpp
@@ -0,0 +1,9 @@
+module template T {
+
+}
+
+expand T(constant 10) {
+
+ constant a = 0
+
+}
diff --git a/compiler/tools/fpp-check/test/template/source_expand_bad_args.ref.txt b/compiler/tools/fpp-check/test/template/source_expand_bad_args.ref.txt
new file mode 100644
index 000000000..1c04c9f7b
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/source_expand_bad_args.ref.txt
@@ -0,0 +1,9 @@
+fpp-check
+[ local path prefix ]/compiler/tools/fpp-check/test/template/source_expand_bad_args.fpp:5.1
+expand T(constant 10) {
+^
+error: expected 0 template arguments, got 1
+template defined here:
+[ local path prefix ]/compiler/tools/fpp-check/test/template/source_expand_bad_args.fpp:1.1
+module template T {
+^
diff --git a/compiler/tools/fpp-check/test/template/source_expand_ok.fpp b/compiler/tools/fpp-check/test/template/source_expand_ok.fpp
new file mode 100644
index 000000000..b0de9cc16
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/source_expand_ok.fpp
@@ -0,0 +1,9 @@
+module template T {
+
+}
+
+expand T {
+
+ constant a = 0
+
+}
diff --git a/compiler/tools/fpp-check/test/template/source_expand_ok.ref.txt b/compiler/tools/fpp-check/test/template/source_expand_ok.ref.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.fpp b/compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.fpp
new file mode 100644
index 000000000..76a128ddc
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.fpp
@@ -0,0 +1,9 @@
+module template T {
+
+}
+
+expand T {
+
+ constant a = b
+
+}
diff --git a/compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.ref.txt b/compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.ref.txt
new file mode 100644
index 000000000..1aa8df51b
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.ref.txt
@@ -0,0 +1,6 @@
+fpp-check
+[ local path prefix ]/compiler/tools/fpp-check/test/template/source_expand_undefined_symbol.fpp:7.16
+ constant a = b
+ ^
+error: symbol b is not defined
+note: looking for a constant here
diff --git a/compiler/tools/fpp-check/test/template/template_def_in_expand.fpp b/compiler/tools/fpp-check/test/template/template_def_in_expand.fpp
new file mode 100644
index 000000000..ecdf65e96
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/template_def_in_expand.fpp
@@ -0,0 +1,11 @@
+module template T1 {
+
+}
+
+expand T1 {
+
+ module template T2 {
+
+ }
+
+}
diff --git a/compiler/tools/fpp-check/test/template/template_def_in_expand.ref.txt b/compiler/tools/fpp-check/test/template/template_def_in_expand.ref.txt
new file mode 100644
index 000000000..ae9b5a94e
--- /dev/null
+++ b/compiler/tools/fpp-check/test/template/template_def_in_expand.ref.txt
@@ -0,0 +1,9 @@
+fpp-check
+[ local path prefix ]/compiler/tools/fpp-check/test/template/template_def_in_expand.fpp:7.3
+ module template T2 {
+ ^
+error: module template definitions cannot appear inside a template expansion
+enclosing template expansion is here:
+[ local path prefix ]/compiler/tools/fpp-check/test/template/template_def_in_expand.fpp:5.1
+expand T1 {
+^
diff --git a/compiler/tools/fpp-check/test/template/tests.sh b/compiler/tools/fpp-check/test/template/tests.sh
index 8a84ef5c4..a065b37a7 100644
--- a/compiler/tools/fpp-check/test/template/tests.sh
+++ b/compiler/tools/fpp-check/test/template/tests.sh
@@ -36,6 +36,7 @@ interfaces_topology_arg_ok
interfaces_topology_arg_order_ok
interfaces_valid_port_instance_name_aliased
module_merge_ok
+nested_expand
nested_scope_resolution
nested_scope_resolution_ok
nested_template_def
@@ -45,6 +46,9 @@ param_conflict_same_name_group
param_same_name_different_groups_ok
parameter_shadow_error
parameter_shadow_ok
+source_expand_bad_args
+source_expand_ok
+source_expand_undefined_symbol
struct_parameter_alias_default_ok
struct_parameter_anon_array_promote
struct_parameter_array_member_default_ok
@@ -55,6 +59,7 @@ struct_parameter_nested_default_bad_arg
struct_parameter_nested_default_ok
struct_parameter_ok
struct_parameter_omitted_member_ok
+template_def_in_expand
type_arg_string
type_param_implied_use
types
From 840123cb4e258027a8c1fe5b8355c85af7e3e2d8 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Wed, 14 Oct 2026 08:28:07 -0700
Subject: [PATCH 39/51] Refactor ExpandTemplates
---
.../main/scala/transform/ExpandTemplates.scala | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index 5a06ebc8f..a340213c8 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -8,25 +8,23 @@ import fpp.compiler.util._
object ExpandTemplates extends AstTransformer
{
- type State = Analysis
-
- type In = State
+ type In = Analysis
type Out = Unit
def default(a: Analysis) =
throw InternalError("ExpandTemplates: Transformer not implemented")
- /** Transform a list in sequence, threading state */
+ /** Transform a list in sequence */
def transformList[A, B](
- s: State,
+ a: Analysis,
list: List[A],
- transform: (State, A) => Result[B]
+ transform: (Analysis, A) => Result[B]
): Result.Result[List[B]] = {
def helper(in: List[A], out: List[B]): Result.Result[List[B]] = {
in match {
case Nil => Right(out)
- case head :: tail => transform(s, head) match {
+ case head :: tail => transform(a, head) match {
case Left(e) => Left(e)
case Right((_, list)) => helper(tail, list :: out)
}
@@ -37,10 +35,10 @@ object ExpandTemplates extends AstTransformer
/** Transform a list and flatten the result */
def transformFlatList[A, B](
- s: State,
+ a: Analysis,
list: List[A],
- transform: (State, A) => Result[List[B]]
- ): Result.Result[List[B]] = transformList(s, list, transform).map(_.flatten)
+ transform: (Analysis, A) => Result[List[B]]
+ ): Result.Result[List[B]] = transformList(a, list, transform).map(_.flatten)
override def transUnit(
a: Analysis,
From 58da0ee4780baa16c15ddb30e57b65b90ed6b7b8 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Wed, 14 Oct 2026 08:38:23 -0700
Subject: [PATCH 40/51] Refactor ExpandTemplates
Add AstUnitTransformer
---
.../main/scala/ast/AstUnitTransformer.scala | 38 +++++++++++++++++++
.../scala/transform/ExpandTemplates.scala | 29 +-------------
2 files changed, 39 insertions(+), 28 deletions(-)
create mode 100644 compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
diff --git a/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala b/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
new file mode 100644
index 000000000..21fe92a3c
--- /dev/null
+++ b/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
@@ -0,0 +1,38 @@
+package fpp.compiler.transform
+
+import fpp.compiler.analysis._
+import fpp.compiler.ast._
+import fpp.compiler.util._
+
+/** Transform an AST, producing no value */
+trait AstUnitTransformer extends AstTransformer
+{
+
+ type Out = Unit
+
+ /** Transform a list in sequence */
+ def transformList[A, B](
+ in: In,
+ list: List[A],
+ transform: (In, A) => Result[B]
+ ): Result.Result[List[B]] = {
+ def helper(inList: List[A], outList: List[B]): Result.Result[List[B]] = {
+ inList match {
+ case Nil => Right(outList)
+ case head :: tail => transform(in, head) match {
+ case Left(e) => Left(e)
+ case Right((_, list)) => helper(tail, list :: outList)
+ }
+ }
+ }
+ helper(list, Nil).map(_.reverse)
+ }
+
+ /** Transform a list and flatten the result */
+ def transformFlatList[A, B](
+ in: In,
+ list: List[A],
+ transform: (In, A) => Result[List[B]]
+ ): Result.Result[List[B]] = transformList(in, list, transform).map(_.flatten)
+
+}
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index a340213c8..ab92a417e 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -5,41 +5,14 @@ import fpp.compiler.ast._
import fpp.compiler.util._
/** Expand any template expansion specifiers that have not yet been expanded */
-object ExpandTemplates extends AstTransformer
+object ExpandTemplates extends AstUnitTransformer
{
type In = Analysis
- type Out = Unit
-
def default(a: Analysis) =
throw InternalError("ExpandTemplates: Transformer not implemented")
- /** Transform a list in sequence */
- def transformList[A, B](
- a: Analysis,
- list: List[A],
- transform: (Analysis, A) => Result[B]
- ): Result.Result[List[B]] = {
- def helper(in: List[A], out: List[B]): Result.Result[List[B]] = {
- in match {
- case Nil => Right(out)
- case head :: tail => transform(a, head) match {
- case Left(e) => Left(e)
- case Right((_, list)) => helper(tail, list :: out)
- }
- }
- }
- helper(list, Nil).map(_.reverse)
- }
-
- /** Transform a list and flatten the result */
- def transformFlatList[A, B](
- a: Analysis,
- list: List[A],
- transform: (Analysis, A) => Result[List[B]]
- ): Result.Result[List[B]] = transformList(a, list, transform).map(_.flatten)
-
override def transUnit(
a: Analysis,
tu: Ast.TransUnit
From f4814f701517675f1d3c2578e2e2403f169f9a1d Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Wed, 14 Oct 2026 08:41:11 -0700
Subject: [PATCH 41/51] Revise comment
---
compiler/lib/src/main/scala/ast/AstUnitTransformer.scala | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala b/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
index 21fe92a3c..e2bab5302 100644
--- a/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
+++ b/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
@@ -4,7 +4,7 @@ import fpp.compiler.analysis._
import fpp.compiler.ast._
import fpp.compiler.util._
-/** Transform an AST, producing no value */
+/** Transform an AST, producing a unit Out value */
trait AstUnitTransformer extends AstTransformer
{
From 5b070c8a6057897f591be18369b142f15d626d1f Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Wed, 14 Oct 2026 09:00:12 -0700
Subject: [PATCH 42/51] Refactor ExpandTemplates and AstUnitTransformer
---
compiler/lib/src/main/scala/ast/AstUnitTransformer.scala | 4 ++++
compiler/lib/src/main/scala/transform/ExpandTemplates.scala | 4 ----
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala b/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
index e2bab5302..b4d2f51e4 100644
--- a/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
+++ b/compiler/lib/src/main/scala/ast/AstUnitTransformer.scala
@@ -35,4 +35,8 @@ trait AstUnitTransformer extends AstTransformer
transform: (In, A) => Result[List[B]]
): Result.Result[List[B]] = transformList(in, list, transform).map(_.flatten)
+ /** Adapt a simple result function to the form of the visitor functions */
+ def resultAdapter[A,B](f: (A, B) => Result.Result[B]) =
+ (a: A, b: B) => for (c <- f(a, b)) yield ((), c)
+
}
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index ab92a417e..dad042111 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -1041,10 +1041,6 @@ object ExpandTemplates extends AstUnitTransformer
}
}
- /** Adapt a simple result function to the form required by the visitor */
- private def resultAdapter[A,B](f: (A, B) => Result.Result[B]) =
- (a: A, b: B) => for (c <- f(a, b)) yield ((), c)
-
private def structMember(
a: Analysis,
node: AstNode[Ast.StructMember]
From d8623ccd274c4e75334fa4c9d993e9a835bdaeee Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 08:32:32 -0700
Subject: [PATCH 43/51] Rename CheckTemplateDefinitions
---
.../{CheckTemplateDefinitions.scala => CheckTemplateDefs.scala} | 2 +-
.../analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
rename compiler/lib/src/main/scala/analysis/CheckSemantics/{CheckTemplateDefinitions.scala => CheckTemplateDefs.scala} (97%)
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefinitions.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
similarity index 97%
rename from compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefinitions.scala
rename to compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
index e11bcbf20..09777f515 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefinitions.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/CheckTemplateDefs.scala
@@ -4,7 +4,7 @@ import fpp.compiler.ast._
import fpp.compiler.util._
/** Check template definitions */
-object CheckTemplateDefinitions
+object CheckTemplateDefs
extends Analyzer
with ModuleAnalyzer
{
diff --git a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
index a8cc751ce..5fe3c2f5a 100644
--- a/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
+++ b/compiler/lib/src/main/scala/analysis/CheckSemantics/ExpandSyntaxAndEnterSymbols.scala
@@ -16,7 +16,7 @@ object ExpandSyntaxAndEnterSymbols {
(a, tul) <- ResolveSpecInclude.transUnitList(a, tul)
tul <- AddStateEnums.transUnitList(tul)
a <- EnterSymbols.visitList(a, tul, EnterSymbols.transUnit)
- a <- CheckTemplateDefinitions.visitList(a, tul, CheckTemplateDefinitions.transUnit)
+ a <- CheckTemplateDefs.visitList(a, tul, CheckTemplateDefs.transUnit)
a <- CheckTemplateExpansions.visitList(a, tul, CheckTemplateExpansions.transUnit)
a <- CheckTemplateUses.visitList(a, tul, CheckTemplateUses.transUnit)
tul <- ExpandTemplates.transformList(a, tul, ExpandTemplates.transUnit)
From b2114450c0dbab383cfe22db9fa976ad10eb7230 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 09:57:48 -0700
Subject: [PATCH 44/51] Revise spec and user's guide
---
docs/fpp-spec.html | 28 +++++++++++++++----
docs/fpp-users-guide.html | 2 +-
.../Template-Expansion-Specifiers.adoc | 17 +++++++++--
.../Defining-and-Using-Module-Templates.adoc | 16 +++++------
4 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html
index c96f47e6b..8303493df 100644
--- a/docs/fpp-spec.html
+++ b/docs/fpp-spec.html
@@ -9306,7 +9306,7 @@ 7.19.1. Syntax
The optional module member list represents the result of
expanding the template.
If a template expansion specifier has a module member
-list, then is called an expanded template.
+list, then it is called an expanded template.
Otherwise it is called an unexpanded template.
@@ -9375,9 +9375,27 @@ 7.19.2. Semantics
-If module-member-sequence is present, then it must not
-transitively contain any module
-template definitions or template expansion specifiers.
+If module-member-sequence is present, then
+
+
+-
+
module-member-sequence must not transitively contain any
+module
+template definitions or template expansion specifiers.
+This rule ensures that the syntax of module-member-sequence could
+be produced by expanding some template.
+
+-
+
module-member-sequence is not required to conform to the syntax produced
+by expanding the template referred to in the specifier.
+
+-
+
All the definitions and uses inside module-member-sequence are
+semantically analyzed in the same way as if module-member-sequence had been
+produced by template expansion.
+
+
+
@@ -14578,7 +14596,7 @@
diff --git a/docs/fpp-users-guide.html b/docs/fpp-users-guide.html
index f8c184f24..a550d3fc9 100644
--- a/docs/fpp-users-guide.html
+++ b/docs/fpp-users-guide.html
@@ -18571,7 +18571,7 @@ 19.4. S
diff --git a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
index 19411a011..30379037a 100644
--- a/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
+++ b/docs/spec/Specifiers/Template-Expansion-Specifiers.adoc
@@ -37,7 +37,7 @@ _module-member-sequence_ is the same as for a
The optional module member list represents the result of
<>.
If a template expansion specifier has a module member
-list, then is called an *expanded template*.
+list, then it is called an *expanded template*.
Otherwise it is called an *unexpanded template*.
==== Semantics
@@ -84,9 +84,20 @@ template argument.
... When _p_ is a type template parameter, _B_
is called a *type parameter definition*.
-. If _module-member-sequence_ is present, then it must not
-transitively contain any <> or template expansion specifiers.
+This rule ensures that the syntax of _module-member-sequence_ could
+be produced by expanding some template.
+
+.. _module-member-sequence_ is not required to conform to the syntax produced
+by expanding the template referred to in the specifier.
+
+.. All the definitions and uses inside _module-member-sequence_ are
+semantically analyzed in the same way as if _module-member-sequence_ had been
+produced by <>.
==== Examples
diff --git a/docs/users-guide/Defining-and-Using-Module-Templates.adoc b/docs/users-guide/Defining-and-Using-Module-Templates.adoc
index c4b0791ce..5d76ecbb5 100644
--- a/docs/users-guide/Defining-and-Using-Module-Templates.adoc
+++ b/docs/users-guide/Defining-and-Using-Module-Templates.adoc
@@ -80,7 +80,7 @@ template definition to be replicated at each expansion point.
After template expansion, the model looks like this:
[source,fpp]
---------
+----
module template T {
constant c = 0
@@ -106,7 +106,7 @@ module N {
}
}
---------
+----
You can see this by running the tool `fpp-to-fpp -e` on the
original model shown above.
@@ -230,7 +230,7 @@ Here we provide 1 and 2 as the arguments, and we write
After template expansion, the model looks like this:
[source,fpp]
---------
+----
module template T(constant p: U32) {
constant c = p
@@ -256,7 +256,7 @@ module N {
}
}
---------
+----
Notice that the `expand T { ... }` syntax provides the bindings
of the constant values at the points of expansion.
@@ -568,7 +568,7 @@ expand M.T
After template expansion, the model looks like this:
[source,fpp]
---------
+----
module M {
constant a = 0
@@ -586,7 +586,7 @@ expand M.T {
constant b = a
}
---------
+----
Notice that in the expanded template, there is a use of the
name `a`.
@@ -627,7 +627,7 @@ expand M.T
Here is the model after expansion:
[source,fpp]
---------
+----
module M {
constant a = 0
@@ -647,7 +647,7 @@ expand M.T {
constant b = a
}
---------
+----
Here the symbol `a` is defined at the point of the expansion.
However, the definition there gives `a` the value 1, whereas
From 99114941d6647af2cdda1159b2c0fd13f84bade8 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 10:05:22 -0700
Subject: [PATCH 45/51] Revise Analysis structure and wiki
---
.../src/main/scala/analysis/Analysis.scala | 4 +-
docs/wiki/Analysis-Data-Structure.asciidoc | 44 +++++++++----------
2 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/Analysis.scala b/compiler/lib/src/main/scala/analysis/Analysis.scala
index 67ecbca15..7f681fe52 100644
--- a/compiler/lib/src/main/scala/analysis/Analysis.scala
+++ b/compiler/lib/src/main/scala/analysis/Analysis.scala
@@ -90,10 +90,10 @@ case class Analysis(
impliedUseMap: Map[AstNode.Id, ImpliedUse.Uses] = Map(),
/** Node ID of the current template definition */
templateDefId: Option[AstNode.Id] = None,
- /** Node ID of the current template expansion */
- templateExpansionId: Option[AstNode.Id] = None,
/** The current template expansion */
templateExpansion: Option[TemplateExpansion] = None,
+ /** Node ID of the current template expansion */
+ templateExpansionId: Option[AstNode.Id] = None,
/** Mapping from template expansion nodes to their expansions */
templateExpansionMap: Map[AstNode.Id, TemplateExpansion] = Map(),
/** The set of symbols defined with a dictionary specifier */
diff --git a/docs/wiki/Analysis-Data-Structure.asciidoc b/docs/wiki/Analysis-Data-Structure.asciidoc
index a651b85fa..862c51171 100644
--- a/docs/wiki/Analysis-Data-Structure.asciidoc
+++ b/docs/wiki/Analysis-Data-Structure.asciidoc
@@ -12,28 +12,6 @@ https://github.com/nasa/fpp/wiki/Analysis#data-structures[component instance sym
to the corresponding
https://github.com/nasa/fpp/wiki/Analysis#data-structures[component instances].
-* *Current template:* The AST node identifier of the template expansion
-specifier whose body is currently being copied, if there is one.
-Used during
-https://github.com/nasa/fpp/wiki/Expand-Templates[template expansion]:
-when it is present, each node visited is copied, and the copy records
-this node as its expansion point.
-
-* *Current template definition:* The AST node identifier of the module
-template definition whose body is currently being traversed, if there is
-one.
-Used during
-https://github.com/nasa/fpp/wiki/Expand-Templates[template expansion] to
-reject a nested template definition and a template expansion inside a
-template.
-
-* *Current template expansion:* The
-https://github.com/nasa/fpp/wiki/Analysis#data-structures[template
-expansion] whose members are currently being analyzed, if there is one.
-Used during
-https://github.com/nasa/fpp/wiki/Check-Uses[check uses] to resolve names
-against the local scope map of the expansion.
-
* *Dependency file set:* The set of
https://github.com/nasa/fpp/wiki/Analysis#data-structures[files]
on which the analysis transitively depends.
@@ -121,6 +99,28 @@ https://github.com/nasa/fpp/wiki/Analysis#data-structures[systems].
The map has either zero elements (if the model is not a system model)
or one element (if the model is a system model).
+* *Template def id:* The AST node identifier of the module
+template definition whose body is currently being traversed, if there is
+one.
+Used during
+https://github.com/nasa/fpp/wiki/Expand-Templates[template expansion] to
+reject a nested template definition and a template expansion inside a
+template.
+
+* *Template expansion:* The
+https://github.com/nasa/fpp/wiki/Analysis#data-structures[template
+expansion] whose members are currently being analyzed, if there is one.
+Used during
+https://github.com/nasa/fpp/wiki/Check-Uses[check uses] to resolve names
+against the local scope map of the expansion.
+
+* *Template expansion id:* The AST node identifier of the template expansion
+specifier whose body is currently being copied, if there is one.
+Used during
+https://github.com/nasa/fpp/wiki/Expand-Templates[template expansion]:
+when it is present, each node visited is copied, and the copy records
+this node as its expansion point.
+
* *Template expansion map*: A map from the AST node identifier of each
template expansion specifier to the corresponding
https://github.com/nasa/fpp/wiki/Analysis#data-structures[template
From 23a9fa5020b70eed6dc37581447d8c26d3b1a572 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 10:16:32 -0700
Subject: [PATCH 46/51] Revise ExpandTemplates
---
.../scala/transform/ExpandTemplates.scala | 11 ++-----
docs/wiki/Expand-Templates.asciidoc | 30 ++++---------------
2 files changed, 9 insertions(+), 32 deletions(-)
diff --git a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
index dad042111..bfd50e6c2 100644
--- a/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
+++ b/compiler/lib/src/main/scala/transform/ExpandTemplates.scala
@@ -845,9 +845,8 @@ object ExpandTemplates extends AstUnitTransformer
}
for {
- a1 <- Right(a.copy(templateDefId = Some(node.id)))
- params <- transformList(a1, data.params, templateParam)
- members <- transformFlatList(a1, data.members, matchModuleMember)
+ params <- transformList(a, data.params, templateParam)
+ members <- transformFlatList(a, data.members, matchModuleMember)
}
yield {
val dataCopy = data.copy(params = params, members = members)
@@ -965,12 +964,8 @@ object ExpandTemplates extends AstUnitTransformer
tmpl <- a.getTemplateSymbol(data.template.id)
// Clone the template body, recording the expansion node so that
// cloned nodes point back at the expansion site.
- // Record the template definition too for diagnostics.
members <- transformFlatList(
- a.copy(
- templateExpansionId = Some(node.id),
- templateDefId = Some(tmpl.node._2.id)
- ),
+ a.copy(templateExpansionId = Some(node.id)),
tmpl.node._2.data.members,
matchModuleMember
)
diff --git a/docs/wiki/Expand-Templates.asciidoc b/docs/wiki/Expand-Templates.asciidoc
index fa522480a..3fdc8e0f6 100644
--- a/docs/wiki/Expand-Templates.asciidoc
+++ b/docs/wiki/Expand-Templates.asciidoc
@@ -59,48 +59,30 @@ visit each member of _d_.
.. *Template expansion specifiers:* If _tum_ is a template expansion
specifier _te_, then
-... If the
-https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[current
-template definition] member of _a_ is present, then report an error for
-a template expansion inside a template, citing the location of the
-enclosing template definition.
-
-... Otherwise
-
-.... Look up the module template definition _t_ that the template name
+... Look up the module template definition _t_ that the template name
of _te_ refers to using the
https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[use-def
map] of _a_.
Report an error if the name does not resolve to a template symbol.
-.... Set the
+... Set the
https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[current
template] member of _a_ to _te_ and the
https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[current
template definition] member of _a_ to _t_.
-.... Copy each member of _t_.
+... Copy each member of _t_.
-.... Restore the current template and current template definition
+... Restore the current template and current template definition
members of _a_.
-.... Replace _te_ with a specifier that has the same identity as _te_
+... Replace _te_ with a specifier that has the same identity as _te_
and that carries the copied members.
.. *Module template definitions:* If _tum_ is a module template
-definition _t_, then
-
-... If the
-https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[current
-template definition] member of _a_ is present, then _t_ is enclosed in
-another module template definition.
-Report an error for a nested template definition, citing the location
-of the enclosing definition.
-
-... Otherwise set the current template definition member of _a_ to _t_,
+definition _t_, then set the current template definition member of _a_ to _t_,
visit the parameters and the members of _t_, and restore the current
template definition member of _a_.
-
.. *Other translation unit members:* For any other translation unit
member _m_, visit _m_.
From 9ecccf13dc4564f0f0a1ce2ced52c8b0d9d198a5 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 11:22:45 -0700
Subject: [PATCH 47/51] Revise AstTransformer
Add cases for expanded and unexpanded forms
---
.../lib/src/main/scala/ast/AstTransformer.scala | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/compiler/lib/src/main/scala/ast/AstTransformer.scala b/compiler/lib/src/main/scala/ast/AstTransformer.scala
index dd4499b4b..c3f6c6649 100644
--- a/compiler/lib/src/main/scala/ast/AstTransformer.scala
+++ b/compiler/lib/src/main/scala/ast/AstTransformer.scala
@@ -288,6 +288,22 @@ trait AstTransformer {
def specTemplateExpandAnnotatedNode(
in: In,
node: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
+ ): ResultAnnotatedNode[Ast.SpecTemplateExpand] =
+ node._2.data.members match {
+ case Some(members) => specTemplateExpandAnnotatedNodeExpanded(in, node, members)
+ case None => specTemplateExpandAnnotatedNodeUnexpanded(in, node)
+ }
+
+ def specTemplateExpandAnnotatedNodeUnexpanded(
+ in: In,
+ node: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]]
+ ): ResultAnnotatedNode[Ast.SpecTemplateExpand] =
+ defaultAnnotatedNode(in, node)
+
+ def specTemplateExpandAnnotatedNodeExpanded(
+ in: In,
+ node: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]],
+ members: List[Ast.ModuleMember]
): ResultAnnotatedNode[Ast.SpecTemplateExpand] =
defaultAnnotatedNode(in, node)
From 83244624451c318313e95536a07899836147b947 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 11:57:29 -0700
Subject: [PATCH 48/51] Revise ast transformers
Refactor AstStateTransformer and ModuleStateTransformer
Revise ModuleStateTransformer to descend into expansions
---
.../main/scala/ast/AstStateTransformer.scala | 9 +++++++++
.../scala/ast/ModuleStateTransformer.scala | 20 ++++++++++++++++---
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/compiler/lib/src/main/scala/ast/AstStateTransformer.scala b/compiler/lib/src/main/scala/ast/AstStateTransformer.scala
index b92cfcd4f..d2be4f968 100644
--- a/compiler/lib/src/main/scala/ast/AstStateTransformer.scala
+++ b/compiler/lib/src/main/scala/ast/AstStateTransformer.scala
@@ -35,6 +35,15 @@ trait AstStateTransformer extends AstTransformer {
yield (pair._1, pair._2.reverse)
}
+ /** Transform a list and flatten the result */
+ def transformFlatList[A, B](
+ s: State,
+ list: List[A],
+ transform: (In, A) => Result[List[B]]
+ ): Result[List[B]] =
+ for ((s, bs) <- transformList(s, list, transform))
+ yield (s, bs.flatten)
+
def tuMember(s: State, member: Ast.TUMember): Result[List[Ast.TUMember]] =
matchModuleMember(s, member)
diff --git a/compiler/lib/src/main/scala/ast/ModuleStateTransformer.scala b/compiler/lib/src/main/scala/ast/ModuleStateTransformer.scala
index 1b09561e4..e372f9f1f 100644
--- a/compiler/lib/src/main/scala/ast/ModuleStateTransformer.scala
+++ b/compiler/lib/src/main/scala/ast/ModuleStateTransformer.scala
@@ -11,15 +11,29 @@ trait ModuleStateTransformer extends AstStateTransformer {
) = {
val (pre, node, post) = aNode
val Ast.DefModule(name, members) = node.data
- for { result <- transformList(s, members, moduleMember) }
+ for ((s1, members1) <- transformFlatList(s, members, moduleMember))
yield {
- val (s1, members1) = result
- val defModule = Ast.DefModule(name, members1.flatten)
+ val defModule = Ast.DefModule(name, members1)
val node1 = AstNode.create(defModule, node.id)
(s1, (pre, node1, post))
}
}
+ override def specTemplateExpandAnnotatedNodeExpanded(
+ s: State,
+ aNode: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]],
+ members: List[Ast.ModuleMember]
+ ) = {
+ val (pre, node, post) = aNode
+ val Ast.SpecTemplateExpand(template, args, _) = node.data
+ for ((s1, members1) <- transformFlatList(s, members, moduleMember))
+ yield {
+ val specTemplateExpand = Ast.SpecTemplateExpand(template, args, Some(members1))
+ val node1 = AstNode.create(specTemplateExpand, node.id)
+ (s1, (pre, node1, post))
+ }
+ }
+
def moduleMember(s: State, member: Ast.ModuleMember): Result[List[Ast.ModuleMember]] =
matchModuleMember(s, member)
From 72f1a73c03b9e77705c2b44dd1e87b910218b2c5 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 13:17:52 -0700
Subject: [PATCH 49/51] Update fpp-syntax tests
---
.../test/include-module-template-expand.fpp | 9 +++++++++
.../test/include-module-template-expand.ref.txt | 9 +++++++++
.../fpp-syntax/test/include-module-template.fpp | 5 +++++
.../fpp-syntax/test/include-module-template.ref.txt | 7 +++++++
compiler/tools/fpp-syntax/test/run | 12 ++++++++++++
compiler/tools/fpp-syntax/test/update-ref | 2 ++
6 files changed, 44 insertions(+)
create mode 100644 compiler/tools/fpp-syntax/test/include-module-template-expand.fpp
create mode 100644 compiler/tools/fpp-syntax/test/include-module-template-expand.ref.txt
create mode 100644 compiler/tools/fpp-syntax/test/include-module-template.fpp
create mode 100644 compiler/tools/fpp-syntax/test/include-module-template.ref.txt
diff --git a/compiler/tools/fpp-syntax/test/include-module-template-expand.fpp b/compiler/tools/fpp-syntax/test/include-module-template-expand.fpp
new file mode 100644
index 000000000..8e05a24cf
--- /dev/null
+++ b/compiler/tools/fpp-syntax/test/include-module-template-expand.fpp
@@ -0,0 +1,9 @@
+module template T {
+
+}
+
+expand T {
+
+ include "constant.fppi"
+
+}
diff --git a/compiler/tools/fpp-syntax/test/include-module-template-expand.ref.txt b/compiler/tools/fpp-syntax/test/include-module-template-expand.ref.txt
new file mode 100644
index 000000000..eff5fbd18
--- /dev/null
+++ b/compiler/tools/fpp-syntax/test/include-module-template-expand.ref.txt
@@ -0,0 +1,9 @@
+def module template
+ ident T
+expand
+ qual ident T
+ @ Included constant
+ def constant
+ ident x
+ literal int 0
+ @< Included constant
diff --git a/compiler/tools/fpp-syntax/test/include-module-template.fpp b/compiler/tools/fpp-syntax/test/include-module-template.fpp
new file mode 100644
index 000000000..b1d2ecf33
--- /dev/null
+++ b/compiler/tools/fpp-syntax/test/include-module-template.fpp
@@ -0,0 +1,5 @@
+module template T {
+
+ include "constant.fppi"
+
+}
diff --git a/compiler/tools/fpp-syntax/test/include-module-template.ref.txt b/compiler/tools/fpp-syntax/test/include-module-template.ref.txt
new file mode 100644
index 000000000..7f8e14b51
--- /dev/null
+++ b/compiler/tools/fpp-syntax/test/include-module-template.ref.txt
@@ -0,0 +1,7 @@
+def module template
+ ident T
+ @ Included constant
+ def constant
+ ident x
+ literal int 0
+ @< Included constant
diff --git a/compiler/tools/fpp-syntax/test/run b/compiler/tools/fpp-syntax/test/run
index 5283847ce..dd4d5d3b2 100755
--- a/compiler/tools/fpp-syntax/test/run
+++ b/compiler/tools/fpp-syntax/test/run
@@ -73,6 +73,16 @@ include_module()
run_test -ia include-module
}
+include_module_template()
+{
+ run_test -ia include-module-template
+}
+
+include_module_template_expand()
+{
+ run_test -ia include-module-template-expand
+}
+
include_parse_error()
{
run_test -i include-parse-error
@@ -177,6 +187,8 @@ include_cycle_1
include_cycle_2
include_missing_file
include_module
+include_module_template
+include_module_template_expand
include_parent_dir
include_parse_error
include_state_machine
diff --git a/compiler/tools/fpp-syntax/test/update-ref b/compiler/tools/fpp-syntax/test/update-ref
index d036a8739..dd294bf94 100755
--- a/compiler/tools/fpp-syntax/test/update-ref
+++ b/compiler/tools/fpp-syntax/test/update-ref
@@ -43,6 +43,8 @@ update -i include-parse-error
update -ia include-component
update -ia include-constant-1 include-constant-1
update -ia include-module
+update -ia include-module-template
+update -ia include-module-template-expand
update -ia include-state-machine
update -ia include-state-machine
update -ia include-subdir
From c57e2340ef00a8d481e028b2e420155abe6618a5 Mon Sep 17 00:00:00 2001
From: Rob Bocchino
Date: Thu, 15 Oct 2026 13:26:21 -0700
Subject: [PATCH 50/51] Refactor fpp-syntax tests
---
.../{template.fpp => module-template.fpp} | 0
...mplate.ref.txt => module-template.ref.txt} | 0
compiler/tools/fpp-syntax/test/run | 58 +++++++++----------
compiler/tools/fpp-syntax/test/update-ref | 10 ++--
4 files changed, 34 insertions(+), 34 deletions(-)
rename compiler/tools/fpp-syntax/test/{template.fpp => module-template.fpp} (100%)
rename compiler/tools/fpp-syntax/test/{template.ref.txt => module-template.ref.txt} (100%)
diff --git a/compiler/tools/fpp-syntax/test/template.fpp b/compiler/tools/fpp-syntax/test/module-template.fpp
similarity index 100%
rename from compiler/tools/fpp-syntax/test/template.fpp
rename to compiler/tools/fpp-syntax/test/module-template.fpp
diff --git a/compiler/tools/fpp-syntax/test/template.ref.txt b/compiler/tools/fpp-syntax/test/module-template.ref.txt
similarity index 100%
rename from compiler/tools/fpp-syntax/test/template.ref.txt
rename to compiler/tools/fpp-syntax/test/module-template.ref.txt
diff --git a/compiler/tools/fpp-syntax/test/run b/compiler/tools/fpp-syntax/test/run
index dd4d5d3b2..99f75df8f 100755
--- a/compiler/tools/fpp-syntax/test/run
+++ b/compiler/tools/fpp-syntax/test/run
@@ -23,6 +23,11 @@ comments()
run_test "" comments
}
+dictionary_specifier()
+{
+ run_test -a dictionary-specifier
+}
+
embedded_tab()
{
run_test "" embedded-tab
@@ -83,14 +88,19 @@ include_module_template_expand()
run_test -ia include-module-template-expand
}
+include_parent_dir()
+{
+ run_test -ia subdir/include-parent-dir
+}
+
include_parse_error()
{
run_test -i include-parse-error
}
-include_parent_dir()
+include_state_machine()
{
- run_test -ia subdir/include-parent-dir
+ run_test -ia include-state-machine
}
include_state_machine()
@@ -103,14 +113,19 @@ include_subdir()
run_test -ia include-subdir
}
-include_state_machine()
+include_topology()
{
- run_test -ia include-state-machine
+ run_test -ia include-topology
}
-include_topology()
+module_template()
{
- run_test -ia include-topology
+ run_test -iea module-template
+}
+
+numeric_shift()
+{
+ run_test "" numeric-shift
}
parse_error()
@@ -128,11 +143,6 @@ syntax()
run_test "" syntax
}
-syntax_kwd_names()
-{
- run_test "" syntax-kwd-names
-}
-
syntax_ast()
{
run_test -a syntax syntax-ast
@@ -143,15 +153,15 @@ syntax_include_ast()
run_test -ia syntax syntax-include-ast
}
-syntax_stdin()
+syntax_kwd_names()
{
- cat syntax.fpp | $fpp_syntax -ia > syntax-stdin.out.txt
- diff -u syntax-stdin.ref.txt syntax-stdin.out.txt > syntax-stdin.diff.txt 2>&1
+ run_test "" syntax-kwd-names
}
-template()
+syntax_stdin()
{
- run_test -iea template
+ cat syntax.fpp | $fpp_syntax -ia > syntax-stdin.out.txt
+ diff -u syntax-stdin.ref.txt syntax-stdin.out.txt > syntax-stdin.diff.txt 2>&1
}
topology_ports()
@@ -165,18 +175,9 @@ two_input_files()
diff -u two-input-files.ref.txt two-input-files.out.txt > two-input-files.diff.txt 2>&1
}
-dictionary_specifier()
-{
- run_test -a dictionary-specifier
-}
-
-numeric_shift()
-{
- run_test "" numeric-shift
-}
-
tests="
comments
+dictionary_specifier
embedded_tab
empty
escaped_strings
@@ -194,6 +195,8 @@ include_parse_error
include_state_machine
include_subdir
include_topology
+module_template
+numeric_shift
parse_error
state_machine
syntax
@@ -201,11 +204,8 @@ syntax_ast
syntax_include_ast
syntax_kwd_names
syntax_stdin
-template
topology_ports
two_input_files
-dictionary_specifier
-numeric_shift
"
run_suite $tests
diff --git a/compiler/tools/fpp-syntax/test/update-ref b/compiler/tools/fpp-syntax/test/update-ref
index dd294bf94..38bc1642e 100755
--- a/compiler/tools/fpp-syntax/test/update-ref
+++ b/compiler/tools/fpp-syntax/test/update-ref
@@ -26,15 +26,15 @@ done
update "" comments
update "" embedded-tab
update "" illegal-character
+update "" numeric-shift
update "" parse-error
update "" syntax
update "" syntax-kwd-names
-update -a state-machine
-update -ia topology-ports
update -a dictionary-specifier
update -a empty
update -a escaped-strings
update -a state-machine
+update -a state-machine
update -a syntax syntax-ast
update -i cycle-1 include-cycle-1
update -i cycle-2 include-cycle-2
@@ -49,11 +49,11 @@ update -ia include-state-machine
update -ia include-state-machine
update -ia include-subdir
update -ia include-topology
-update -ia topology-ports
-update -iea template
update -ia subdir/include-parent-dir
update -ia syntax syntax-include-ast
-update "" numeric-shift
+update -ia topology-ports
+update -ia topology-ports
+update -iea module-template
cat syntax.fpp | $fpp_syntax -ia 2>&1 > syntax-stdin.ref.txt
From 9e4c73b083c48472faa9b908a016eb43df04890a Mon Sep 17 00:00:00 2001
From: Bevin K Duckett
Date: Fri, 16 Oct 2026 10:34:25 -0700
Subject: [PATCH 51/51] Include annotation for packets from FPP in dictionary
---
.../DictionaryJsonWriter/DictionaryJsonEncoder.scala | 8 ++++++--
compiler/tools/fpp-to-dict/test/dictionary.schema.json | 6 ++++++
.../test/top/FirstTopTopologyDictionary.ref.json | 9 ++++++---
compiler/tools/fpp-to-dict/test/top/multipleTops.fpp | 3 +++
4 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/compiler/lib/src/main/scala/codegen/DictionaryJsonWriter/DictionaryJsonEncoder.scala b/compiler/lib/src/main/scala/codegen/DictionaryJsonWriter/DictionaryJsonEncoder.scala
index 7a625e7f3..e5beed02f 100644
--- a/compiler/lib/src/main/scala/codegen/DictionaryJsonWriter/DictionaryJsonEncoder.scala
+++ b/compiler/lib/src/main/scala/codegen/DictionaryJsonWriter/DictionaryJsonEncoder.scala
@@ -568,10 +568,12 @@ case class DictionaryJsonEncoder(
/** JSON Encoding for Telemetry Packet Sets */
private implicit def tlmPacketSetEncoder: Encoder[(Name.Unqualified, TlmPacketSet)] = new Encoder[(Name.Unqualified, TlmPacketSet)] {
override def apply(entry: (Name.Unqualified, TlmPacketSet)): Json = {
- Json.obj(
+ val (setPreA, _, setPostA) = entry._2.aNode
+ val json = Json.obj(
"name" -> entry._1.toString.asJson,
"members" -> entry._2.packetMap.map((id, packet) => {
- Json.obj(
+ val (preA, _, postA) = packet.aNode
+ val packetJson = Json.obj(
"name" -> packet.getName.asJson,
"id" -> id.asJson,
"group" -> packet.group.asJson,
@@ -580,12 +582,14 @@ case class DictionaryJsonEncoder(
s"${e.instance.toString}.${e.tlmChannel.getName}"
}).asJson
)
+ jsonWithOptionalValues(packetJson, Map("annotation" -> concatAnnotations(preA, postA)))
}).asJson,
"omitted" -> entry._2.omittedIdSet.map(tlmId => {
val e = dictionary.tlmChannelEntryMap(tlmId)
s"${e.instance.toString}.${e.tlmChannel.getName}"
}).toList.sorted.asJson
)
+ jsonWithOptionalValues(json, Map("annotation" -> concatAnnotations(setPreA, setPostA)))
}
}
diff --git a/compiler/tools/fpp-to-dict/test/dictionary.schema.json b/compiler/tools/fpp-to-dict/test/dictionary.schema.json
index f9335794b..a0d82cb72 100644
--- a/compiler/tools/fpp-to-dict/test/dictionary.schema.json
+++ b/compiler/tools/fpp-to-dict/test/dictionary.schema.json
@@ -114,6 +114,9 @@
"items": {
"type": "string"
}
+ },
+ "annotation": {
+ "type": "string"
}
},
"required": [
@@ -577,6 +580,9 @@
"items": {
"type": "string"
}
+ },
+ "annotation": {
+ "type": "string"
}
},
"required": [
diff --git a/compiler/tools/fpp-to-dict/test/top/FirstTopTopologyDictionary.ref.json b/compiler/tools/fpp-to-dict/test/top/FirstTopTopologyDictionary.ref.json
index c0f8226ee..35e2facc8 100644
--- a/compiler/tools/fpp-to-dict/test/top/FirstTopTopologyDictionary.ref.json
+++ b/compiler/tools/fpp-to-dict/test/top/FirstTopTopologyDictionary.ref.json
@@ -1252,7 +1252,8 @@
"members" : [
"Module1.myFirstC1.TlmChannel1",
"Module1.myFirstC1.TlmChannel2"
- ]
+ ],
+ "annotation" : "Pre annotation for MyTlmPacket1"
},
{
"name" : "MyTlmPacket2",
@@ -1260,14 +1261,16 @@
"group" : 1,
"members" : [
"Module1.myFirstC2.TlmChannel1"
- ]
+ ],
+ "annotation" : "Pre annotation for MyTlmPacket2"
}
],
"omitted" : [
"Module1.myFirstC1.TlmChannel3",
"Module1.myFirstC2.TlmChannel2",
"Module1.myFirstC2.TlmChannel3"
- ]
+ ],
+ "annotation" : "Pre annotation for Packets"
}
]
}
diff --git a/compiler/tools/fpp-to-dict/test/top/multipleTops.fpp b/compiler/tools/fpp-to-dict/test/top/multipleTops.fpp
index 62f693e48..670cfd3c8 100644
--- a/compiler/tools/fpp-to-dict/test/top/multipleTops.fpp
+++ b/compiler/tools/fpp-to-dict/test/top/multipleTops.fpp
@@ -300,12 +300,15 @@ module Module1 {
myFirstC1.pOut -> myFirstC2.pIn
}
+ @ Pre annotation for Packets
telemetry packets Packets {
+ @ Pre annotation for MyTlmPacket1
packet MyTlmPacket1 id 0 group 0 {
Module1.myFirstC1.TlmChannel1
Module1.myFirstC1.TlmChannel2
}
+ @ Pre annotation for MyTlmPacket2
packet MyTlmPacket2 id 1 group 1 {
Module1.myFirstC2.TlmChannel1
}