From c423feca7583bd474ff982cd0baa7df052698126 Mon Sep 17 00:00:00 2001
From: jawest
Date: Wed, 28 Aug 2024 17:08:24 -0700
Subject: [PATCH 01/73] update spec, add unmatched keyword
---
compiler/lib/src/main/scala/ast/Ast.scala | 10 ++++
.../lib/src/main/scala/syntax/Lexer.scala | 1 +
.../lib/src/main/scala/syntax/Parser.scala | 14 ++++--
.../lib/src/main/scala/syntax/Token.scala | 1 +
docs/README.adoc | 8 +++
docs/code-prettify/run_prettify.js | 1 +
docs/fpp-spec.html | 49 ++++++++++++++-----
.../Definitions/Topology-Definitions.adoc | 24 +++++----
docs/spec/Lexical-Elements.adoc | 1 +
.../Connection-Graph-Specifiers.adoc | 11 ++++-
editors/emacs/fpp-mode.el | 2 +-
editors/vim/fpp.vim | 1 +
12 files changed, 95 insertions(+), 28 deletions(-)
diff --git a/compiler/lib/src/main/scala/ast/Ast.scala b/compiler/lib/src/main/scala/ast/Ast.scala
index 26768d018..d65eb7755 100644
--- a/compiler/lib/src/main/scala/ast/Ast.scala
+++ b/compiler/lib/src/main/scala/ast/Ast.scala
@@ -374,6 +374,7 @@ object Ast {
/** Connection */
final case class Connection(
+ unmatched: Option[ConnectionMatching],
fromPort: AstNode[PortInstanceIdentifier],
fromIndex: Option[AstNode[Expr]],
toPort: AstNode[PortInstanceIdentifier],
@@ -706,4 +707,13 @@ object Ast {
}
}
+ sealed trait ConnectionMatching
+ object ConnectionMatching {
+ case object Unmatched extends ConnectionMatching {
+ override def toString = "unmatched"
+ }
+ case object PossiblyMatched extends ConnectionMatching {
+ override def toString = "possibly matched"
+ }
+ }
}
diff --git a/compiler/lib/src/main/scala/syntax/Lexer.scala b/compiler/lib/src/main/scala/syntax/Lexer.scala
index 5002f6dbc..f3d84486b 100644
--- a/compiler/lib/src/main/scala/syntax/Lexer.scala
+++ b/compiler/lib/src/main/scala/syntax/Lexer.scala
@@ -324,6 +324,7 @@ object Lexer extends RegexParsers {
("topology", (u: Unit) => Token.TOPOLOGY()),
("true", (u: Unit) => Token.TRUE()),
("type", (u: Unit) => Token.TYPE()),
+ ("unmatched", (u: Unit) => Token.UNMATCHED()),
("update", (u: Unit) => Token.UPDATE()),
("warning", (u: Unit) => Token.WARNING()),
("with", (u: Unit) => Token.WITH()),
diff --git a/compiler/lib/src/main/scala/syntax/Parser.scala b/compiler/lib/src/main/scala/syntax/Parser.scala
index 136495a86..b5020164a 100644
--- a/compiler/lib/src/main/scala/syntax/Parser.scala
+++ b/compiler/lib/src/main/scala/syntax/Parser.scala
@@ -46,9 +46,10 @@ object Parser extends Parsers {
def connection: Parser[Ast.SpecConnectionGraph.Connection] = {
def connectionPort = node(portInstanceIdentifier) ~! opt(index)
- connectionPort ~! (rarrow ~>! connectionPort) ^^ {
- case (fromPort ~ fromIndex) ~ (toPort ~ toIndex) => {
+ opt(unmatched) ~! connectionPort ~! (rarrow ~>! connectionPort) ^^ {
+ case maybeUnmatched ~ (fromPort ~ fromIndex) ~ (toPort ~ toIndex) => {
Ast.SpecConnectionGraph.Connection(
+ maybeUnmatched,
fromPort,
fromIndex,
toPort,
@@ -388,7 +389,9 @@ object Parser extends Parsers {
def specConnectionGraph: Parser[Ast.SpecConnectionGraph] = {
def directGraph = {
(connections ~> ident) ~! (lbrace ~>! elementSequence(connection, comma) <~! rbrace) ^^ {
- case ident ~ connections => Ast.SpecConnectionGraph.Direct(ident, connections)
+ case ident ~ connections => {
+ Ast.SpecConnectionGraph.Direct(ident, connections)
+ }
}
}
def patternGraph = {
@@ -911,6 +914,11 @@ object Parser extends Parsers {
private def typeToken = accept("type", { case t : Token.TYPE => t })
+ private def unmatched = accept("unmatched", {
+ case t : Token.UNMATCHED => Ast.ConnectionMatching.Unmatched
+ case _ => Ast.ConnectionMatching.PossiblyMatched
+ })
+
private def update = accept("update", { case t : Token.UPDATE => t })
private def warning = accept("warning", { case t : Token.WARNING => t })
diff --git a/compiler/lib/src/main/scala/syntax/Token.scala b/compiler/lib/src/main/scala/syntax/Token.scala
index fd735b5eb..cfc58b32c 100644
--- a/compiler/lib/src/main/scala/syntax/Token.scala
+++ b/compiler/lib/src/main/scala/syntax/Token.scala
@@ -115,6 +115,7 @@ object Token {
final case class U32() extends Token
final case class U64() extends Token
final case class U8() extends Token
+ final case class UNMATCHED() extends Token
final case class UNUSED() extends Token
final case class UPDATE() extends Token
final case class WARNING() extends Token
diff --git a/docs/README.adoc b/docs/README.adoc
index 54ff2a773..d6ad7b97f 100644
--- a/docs/README.adoc
+++ b/docs/README.adoc
@@ -11,3 +11,11 @@ system:
Once you have these tools installed, you can run `redo` in this directory
to regenerate the HTML files from the AsciiDoc source files.
+
+
+== Adding Keywords to FPP Specification
+. To add a new FPP keyword, first update the Lexical Elements section of the FPP spec.
+. Next, update the `doc/code-prettify/run_prettify.js` file so it includes the new keyword.
+. Doing this will add highlight the keyword in the FPP spec.
+. Finally, update `editors/emacs/fpp-mode.el` and `editors/vim/fpp.vim` so the emacs and vim
+editors syntax highlighting for the new keyword.
\ No newline at end of file
diff --git a/docs/code-prettify/run_prettify.js b/docs/code-prettify/run_prettify.js
index d791d31d6..a8a498e07 100644
--- a/docs/code-prettify/run_prettify.js
+++ b/docs/code-prettify/run_prettify.js
@@ -479,6 +479,7 @@ var IN_GLOBAL_SCOPE = false;
"time," +
"topology," +
"type," +
+ "unmatched," +
"update," +
"warning," +
"with," +
diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html
index 06d2d3c6f..601aee82d 100644
--- a/docs/fpp-spec.html
+++ b/docs/fpp-spec.html
@@ -140,7 +140,7 @@
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
-#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
@@ -162,6 +162,7 @@
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
+body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
@@ -327,7 +328,7 @@
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
-sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+sup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
@@ -1006,6 +1007,7 @@
3.1. Reserved Words
guarded
health
high
+hook
id
import
include
@@ -1053,6 +1055,7 @@
3.1. Reserved Words
topology
true
type
+unmatched
update
warning
with
@@ -2861,7 +2864,12 @@
-
For each connection \$c_1\$ with an endpoint at I. \$p_1\$:
+
Any connection that names I. \$p_1\$ or I. \$p_2\$
+is match constrained. If a match constrained connection is marked
+unmatched then it is unmatched; otherwise it is matched.
+
+
+
For each matched connection \$c_1\$ with an endpoint at I. \$p_1\$:
@@ -2869,24 +2877,24 @@
-
Check that there is one and only one connection
-\$c_2\$ from I' to I. \$p_2\$.
+
Check that there is one
+and only one connection \$c_2\$ from I' to I. \$p_2\$.
Check that the connections \$c_2\$ computed in the previous
-step are all the connections at I. \$p_2\$.
+step are all the matched connections at I. \$p_2\$.
-
For each pair \$(c_1,c_2)\$ that has both port numbers assigned,
-check that the port numbers match.
-For each pair \$(c_1,c_2)\$ that has exactly one port number assigned,
+
For each pair P with \$(c_1,c_2)\$ computed in step b, if P
+has both numbers assigned, check that the port numbers match.
+For each P that has exactly one port number assigned,
assign the other one to match.
-
Traverse the pairs \$(c_1,c_2)\$ according to the
+
Traverse the pairs \$(c_1,c_2)\$ computed in step b according to the
order of the connections \$c_1\$, least to greatest.
For each pair \$(c_1,c_2)\$ that does not yet have assigned
port numbers, find the lowest available port number
@@ -3482,7 +3490,10 @@
The optional keyword unmatched, if present, specifies that
+the connection is explicitly unmatched. unmatched must only be used on
+matched connections.
+
+
The component instance named in I
must be available in the enclosing topology,
either through
@@ -4595,6 +4612,9 @@
6.11.1. Syntax
drop
+
+
hook
+
@@ -4747,6 +4767,9 @@
6.11.2. Semantics
drop means that the message is dropped.
+
+
hook means that the message is passed to a user-supplied hook function.
+
@@ -8551,7 +8574,7 @@
20.4. Translation Tools
diff --git a/docs/spec/Definitions/Topology-Definitions.adoc b/docs/spec/Definitions/Topology-Definitions.adoc
index 8eeeb0896..bc605e768 100644
--- a/docs/spec/Definitions/Topology-Definitions.adoc
+++ b/docs/spec/Definitions/Topology-Definitions.adoc
@@ -140,24 +140,28 @@ For each instance _I_ in the topology:
. For each
<>
`match` stem:[p_1] `with` stem:[p_2] appearing in the definition of _C_:
+
+.. Any connection that names _I_ `.` stem:[p_1] or _I_ `.` stem:[p_2]
+is *match constrained*. If a match constrained connection is marked
+`unmatched` then it is *unmatched*; otherwise it is *matched*.
-.. For each connection stem:[c_1] with an endpoint at _I_ `.` stem:[p_1]:
-
+.. For each matched connection stem:[c_1] with an endpoint at _I_ `.` stem:[p_1]:
+
... Let _I'_ be the component instance at the other endpoint
of stem:[c_1].
-... Check that there is one and only one connection
-stem:[c_2] from _I'_ to _I_ `.` stem:[p_2].
+... Check that there is one
+and only one connection stem:[c_2] from _I'_ to _I_ `.` stem:[p_2].
-.. Check that the connections stem:[c_2] computed in the previous
-step are all the connections at _I_ `.` stem:[p_2].
+.. Check that the connections stem:[c_2] computed in the previous
+step are all the matched connections at _I_ `.` stem:[p_2].
-.. For each pair stem:[(c_1,c_2)] that has both port numbers assigned,
-check that the port numbers match.
-For each pair stem:[(c_1,c_2)] that has exactly one port number assigned,
+.. For each pair _P_ with stem:[(c_1,c_2)] computed in step b, if _P_
+has both numbers assigned, check that the port numbers match.
+For each _P_ that has exactly one port number assigned,
assign the other one to match.
-.. Traverse the pairs stem:[(c_1,c_2)] according to the
+.. Traverse the pairs stem:[(c_1,c_2)] computed in step b according to the
<> of the connections stem:[c_1], least to greatest.
For each pair stem:[(c_1,c_2)] that does not yet have assigned
diff --git a/docs/spec/Lexical-Elements.adoc b/docs/spec/Lexical-Elements.adoc
index 8f1234414..a1baf6016 100644
--- a/docs/spec/Lexical-Elements.adoc
+++ b/docs/spec/Lexical-Elements.adoc
@@ -118,6 +118,7 @@ time
topology
true
type
+unmatched
update
warning
with
diff --git a/docs/spec/Specifiers/Connection-Graph-Specifiers.adoc b/docs/spec/Specifiers/Connection-Graph-Specifiers.adoc
index 77cc42eec..32747c6bd 100644
--- a/docs/spec/Specifiers/Connection-Graph-Specifiers.adoc
+++ b/docs/spec/Specifiers/Connection-Graph-Specifiers.adoc
@@ -34,6 +34,9 @@ which each element is a *connection*,
and the terminating punctuation is a comma.
A connection is the following:
+_[_
+`unmatched`
+_]_
<>
_[_
`[`
@@ -77,10 +80,16 @@ A direct graph specifier directly specifies a named connection graph.
the connection graph.
. The connection sequence specifies the set of connections in the graph.
-For each connection _C_:
+For each
+<> connection _C_:
.. For each of the two port instance identifiers _I_ appearing in _C_:
+... The optional keyword `unmatched`, if present, specifies that
+the connection is explicitly unmatched. `unmatched` must only be used on
+matched connections.
+
... The component instance named in _I_
must be available in the enclosing topology,
either through
diff --git a/editors/emacs/fpp-mode.el b/editors/emacs/fpp-mode.el
index 9b0f20584..142ed7282 100644
--- a/editors/emacs/fpp-mode.el
+++ b/editors/emacs/fpp-mode.el
@@ -50,7 +50,7 @@
"queue" "queued" "raw" "recv" "red" "ref" "reg"
"resp" "save" "serial" "set" "severity" "size"
"stack" "sync" "telemetry" "text" "throttle"
- "time" "true" "update" "warning" "with" "yellow")
+ "time" "true" "unmatched" "update" "warning" "with" "yellow")
"All non-definition keywords for FPP.")
(defconst fpp-mode-types
diff --git a/editors/vim/fpp.vim b/editors/vim/fpp.vim
index 33ca7edf8..e7d92e4f6 100644
--- a/editors/vim/fpp.vim
+++ b/editors/vim/fpp.vim
@@ -83,6 +83,7 @@ syn keyword fppKeyword time
syn keyword fppKeyword topology
syn keyword fppKeyword true
syn keyword fppKeyword type
+syn keyword fppKeyword unmatched
syn keyword fppKeyword update
syn keyword fppKeyword warning
syn keyword fppKeyword with
From c734be20c65d45faaff8043b0a1a8c9e28358f1c Mon Sep 17 00:00:00 2001
From: jawest
Date: Wed, 28 Aug 2024 17:10:26 -0700
Subject: [PATCH 02/73] fix formatting
---
docs/README.adoc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/README.adoc b/docs/README.adoc
index d6ad7b97f..b2b16964a 100644
--- a/docs/README.adoc
+++ b/docs/README.adoc
@@ -15,7 +15,7 @@ to regenerate the HTML files from the AsciiDoc source files.
== Adding Keywords to FPP Specification
. To add a new FPP keyword, first update the Lexical Elements section of the FPP spec.
-. Next, update the `doc/code-prettify/run_prettify.js` file so it includes the new keyword.
-. Doing this will add highlight the keyword in the FPP spec.
+. Next, update the `doc/code-prettify/run_prettify.js` file so it includes the new keyword.
+Doing this will add syntax highlighting the keyword in the FPP spec.
. Finally, update `editors/emacs/fpp-mode.el` and `editors/vim/fpp.vim` so the emacs and vim
editors syntax highlighting for the new keyword.
\ No newline at end of file
From 1b8ff6be922c900780d3d059591ee4504dd0d06a Mon Sep 17 00:00:00 2001
From: jawest
Date: Thu, 5 Sep 2024 17:45:49 -0700
Subject: [PATCH 03/73] update matched port numbering, add connection matching
semantics
---
.../scala/analysis/Semantics/Connection.scala | 46 ++++++++++++++++++-
.../MatchedPortNumbering.scala | 24 ++++++----
.../ResolveTopology/PatternResolver.scala | 2 +-
compiler/lib/src/main/scala/ast/Ast.scala | 2 +-
.../XmlFppWriter/TopologyXmlFppWriter.scala | 1 +
.../lib/src/main/scala/syntax/Parser.scala | 9 ++--
compiler/lib/src/main/scala/util/Error.scala | 5 ++
7 files changed, 70 insertions(+), 19 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala b/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
index 7dc1d04f4..59464f1cb 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
@@ -5,6 +5,7 @@ import fpp.compiler.util._
/** An FPP connection */
case class Connection(
+ connectionMatching: Connection.ConnectionMatching,
/** The from endpoint */
from: Connection.Endpoint,
/** The to endpoint */
@@ -141,7 +142,8 @@ object Connection {
for {
from <- Endpoint.fromAst(a, connection.fromPort, connection.fromIndex)
to <- Endpoint.fromAst(a, connection.toPort, connection.toIndex)
- connection <- Right(Connection(from, to))
+ connectionMatching <- ConnectionMatching.fromAst(connection.connectionMatching, from, to)
+ connection <- Right(Connection(connectionMatching, from, to))
_ <- connection.checkDirections
_ <- connection.checkTypes
_ <- connection.checkSerialWithTypedInput
@@ -184,7 +186,30 @@ object Connection {
else Left(SemanticError.InvalidPortNumber(loc, n, name, size, specLoc))
case None => Right(())
}
+ }
+ case class ConnectionMatching(
+ isUnmatched: Boolean
+ ) {
+
+ def checkMatchingPorts(from: Connection.Endpoint, to: Connection.Endpoint): Result.Result[Unit] = {
+ def checkMatch(pml: List[Component.PortMatching], pi: PortInstance): Result.Result[Unit] =
+ if(pml.exists(pm => pi.equals(pm.instance1) || pi.equals(pm.instance2))) then Right(())
+ else Left(SemanticError.MissingPortMatching(pi.getLoc))
+
+ val fromPi = from.port.portInstance
+ val toPi = to.port.portInstance
+ val fromPml = from.port.componentInstance.component.portMatchingList
+ val toPml = to.port.componentInstance.component.portMatchingList
+
+ if(fromPml.isEmpty & toPml.isEmpty) then Left(SemanticError.MissingPortMatching(from.loc))
+ else {
+ for {
+ _ <- if(!fromPml.isEmpty) then checkMatch(fromPml, fromPi) else Right(())
+ _ <- if(!toPml.isEmpty) then checkMatch(toPml, toPi) else Right(())
+ } yield Right(())
+ }
+ }
}
object Endpoint {
@@ -207,4 +232,23 @@ object Connection {
}
+ object ConnectionMatching {
+
+ def fromAst(
+ connectionMatchingAst: Ast.ConnectionMatching,
+ from: Connection.Endpoint,
+ to: Connection.Endpoint
+ ): Result.Result[ConnectionMatching] = for {
+ connectionMatching <- connectionMatchingAst match {
+ case Ast.ConnectionMatching.Unmatched => Right(ConnectionMatching(true))
+ case _ => Right(ConnectionMatching(false))
+ }
+ _ <- {
+ if(connectionMatching.isUnmatched) then connectionMatching.checkMatchingPorts(from, to)
+ else Right(())
+ }
+ } yield connectionMatching
+
+ }
+
}
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala
index 0264bc048..065904400 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala
@@ -161,17 +161,21 @@ object MatchedPortNumbering {
val pii = PortInstanceIdentifier(ci, pi)
val cs = t.getConnectionsAt(pii).toList.sorted
Result.foldLeft (cs) (empty) ((m, c) => {
- val piiRemote = c.getOtherEndpoint(pi).port
- val ciRemote = piiRemote.componentInstance
- m.get(ciRemote) match {
- case Some(cPrev) => Left(
- SemanticError.DuplicateMatchedConnection(
- c.getLoc,
- cPrev.getLoc,
- portMatching.getLoc
+ if(c.connectionMatching.isUnmatched)
+ Right(m)
+ else {
+ val piiRemote = c.getOtherEndpoint(pi).port
+ val ciRemote = piiRemote.componentInstance
+ m.get(ciRemote) match {
+ case Some(cPrev) => Left(
+ SemanticError.DuplicateMatchedConnection(
+ c.getLoc,
+ cPrev.getLoc,
+ portMatching.getLoc
+ )
)
- )
- case None => Right(m + (ciRemote -> c))
+ case None => Right(m + (ciRemote -> c))
+ }
}
})
}
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
index 7c66be44d..da95d3790 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
@@ -108,7 +108,7 @@ object PatternResolver {
) = {
val from = Connection.Endpoint(loc, fromPii)
val to = Connection.Endpoint(loc, toPii)
- Connection(from, to)
+ Connection(Connection.ConnectionMatching(false), from, to)
}
private def missingPort[T](
diff --git a/compiler/lib/src/main/scala/ast/Ast.scala b/compiler/lib/src/main/scala/ast/Ast.scala
index d65eb7755..085481776 100644
--- a/compiler/lib/src/main/scala/ast/Ast.scala
+++ b/compiler/lib/src/main/scala/ast/Ast.scala
@@ -374,7 +374,7 @@ object Ast {
/** Connection */
final case class Connection(
- unmatched: Option[ConnectionMatching],
+ connectionMatching: ConnectionMatching,
fromPort: AstNode[PortInstanceIdentifier],
fromIndex: Option[AstNode[Expr]],
toPort: AstNode[PortInstanceIdentifier],
diff --git a/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala b/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala
index fa6843ef1..d5b710ae7 100644
--- a/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala
+++ b/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala
@@ -129,6 +129,7 @@ object TopologyXmlFppWriter extends LineUtils {
}
yield {
Ast.SpecConnectionGraph.Connection(
+ Ast.ConnectionMatching.PossiblyMatched,
from._1,
from._2,
to._1,
diff --git a/compiler/lib/src/main/scala/syntax/Parser.scala b/compiler/lib/src/main/scala/syntax/Parser.scala
index b5020164a..9df852482 100644
--- a/compiler/lib/src/main/scala/syntax/Parser.scala
+++ b/compiler/lib/src/main/scala/syntax/Parser.scala
@@ -47,9 +47,9 @@ object Parser extends Parsers {
def connection: Parser[Ast.SpecConnectionGraph.Connection] = {
def connectionPort = node(portInstanceIdentifier) ~! opt(index)
opt(unmatched) ~! connectionPort ~! (rarrow ~>! connectionPort) ^^ {
- case maybeUnmatched ~ (fromPort ~ fromIndex) ~ (toPort ~ toIndex) => {
+ case unmatched ~ (fromPort ~ fromIndex) ~ (toPort ~ toIndex) => {
Ast.SpecConnectionGraph.Connection(
- maybeUnmatched,
+ unmatched.getOrElse(Ast.ConnectionMatching.PossiblyMatched),
fromPort,
fromIndex,
toPort,
@@ -914,10 +914,7 @@ object Parser extends Parsers {
private def typeToken = accept("type", { case t : Token.TYPE => t })
- private def unmatched = accept("unmatched", {
- case t : Token.UNMATCHED => Ast.ConnectionMatching.Unmatched
- case _ => Ast.ConnectionMatching.PossiblyMatched
- })
+ private def unmatched = accept("unmatched", { case t : Token.UNMATCHED => Ast.ConnectionMatching.Unmatched })
private def update = accept("update", { case t : Token.UPDATE => t })
diff --git a/compiler/lib/src/main/scala/util/Error.scala b/compiler/lib/src/main/scala/util/Error.scala
index adacc24ab..f8ce44252 100644
--- a/compiler/lib/src/main/scala/util/Error.scala
+++ b/compiler/lib/src/main/scala/util/Error.scala
@@ -192,6 +192,8 @@ sealed trait Error {
case SemanticError.MissingConnection(loc, matchingLoc) =>
Error.print (Some(loc)) ("no match for this connection")
printMatchingLoc(matchingLoc)
+ case SemanticError.MissingPortMatching(loc) =>
+ Error.print (Some(loc)) ("unmatched connections must use port matching")
case SemanticError.MissingPort(loc, specMsg, portMsg) =>
Error.print (Some(loc)) (s"component with $specMsg must have $portMsg")
case SemanticError.OverlappingIdRanges(
@@ -472,6 +474,9 @@ object SemanticError {
specMsg: String,
portmsg: String
) extends Error
+ final case class MissingPortMatching(
+ loc: Location
+ ) extends Error
/** Overlapping ID ranges */
final case class OverlappingIdRanges(
maxId1: BigInt,
From d3c3de33a86c534e2daaac01f43be389cb6e66e6 Mon Sep 17 00:00:00 2001
From: jawest
Date: Thu, 5 Sep 2024 17:51:50 -0700
Subject: [PATCH 04/73] update docs readme
---
docs/README.adoc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/README.adoc b/docs/README.adoc
index b2b16964a..39e6acd2a 100644
--- a/docs/README.adoc
+++ b/docs/README.adoc
@@ -16,6 +16,6 @@ to regenerate the HTML files from the AsciiDoc source files.
== Adding Keywords to FPP Specification
. To add a new FPP keyword, first update the Lexical Elements section of the FPP spec.
. Next, update the `doc/code-prettify/run_prettify.js` file so it includes the new keyword.
-Doing this will add syntax highlighting the keyword in the FPP spec.
+Doing this will add syntax highlighting to the keyword in the FPP spec.
. Finally, update `editors/emacs/fpp-mode.el` and `editors/vim/fpp.vim` so the emacs and vim
editors syntax highlighting for the new keyword.
\ No newline at end of file
From ed4e051a19e873fd90b306fa0f41c384705680c6 Mon Sep 17 00:00:00 2001
From: jawest
Date: Mon, 16 Sep 2024 08:55:59 -0700
Subject: [PATCH 05/73] cleanup
---
.../scala/analysis/Semantics/Connection.scala | 67 ++++++-------------
.../MatchedPortNumbering.scala | 2 +-
.../ResolveTopology/PatternResolver.scala | 2 +-
compiler/lib/src/main/scala/ast/Ast.scala | 12 +---
.../src/main/scala/codegen/AstWriter.scala | 2 +-
.../src/main/scala/codegen/FppWriter.scala | 10 +--
.../XmlFppWriter/TopologyXmlFppWriter.scala | 2 +-
.../lib/src/main/scala/syntax/Parser.scala | 4 +-
docs/README.adoc | 8 ---
9 files changed, 33 insertions(+), 76 deletions(-)
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala b/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
index 59464f1cb..9af4c027a 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
@@ -5,7 +5,7 @@ import fpp.compiler.util._
/** An FPP connection */
case class Connection(
- connectionMatching: Connection.ConnectionMatching,
+ isUnmatched: Boolean,
/** The from endpoint */
from: Connection.Endpoint,
/** The to endpoint */
@@ -104,6 +104,18 @@ case class Connection(
}
}
+ def checkMatchConstraint: Boolean = {
+ def portMatchingExists(pml: List[Component.PortMatching], pi: PortInstance): Boolean =
+ pml.exists(pm => pi.equals(pm.instance1) || pi.equals(pm.instance2))
+
+ val fromPi = from.port.portInstance
+ val toPi = to.port.portInstance
+ val fromPml = from.port.componentInstance.component.portMatchingList
+ val toPml = to.port.componentInstance.component.portMatchingList
+
+ portMatchingExists(fromPml, fromPi) || portMatchingExists(toPml, toPi)
+ }
+
/** Compare two connections */
override def compare(that: Connection) = {
val fromCompare = this.from.compare(that.from)
@@ -142,11 +154,16 @@ object Connection {
for {
from <- Endpoint.fromAst(a, connection.fromPort, connection.fromIndex)
to <- Endpoint.fromAst(a, connection.toPort, connection.toIndex)
- connectionMatching <- ConnectionMatching.fromAst(connection.connectionMatching, from, to)
- connection <- Right(Connection(connectionMatching, from, to))
+ connection <- Right(Connection(connection.isUnmatched, from, to))
_ <- connection.checkDirections
_ <- connection.checkTypes
_ <- connection.checkSerialWithTypedInput
+ _ <- {
+ if !connection.checkMatchConstraint & connection.isUnmatched then
+ Left(SemanticError.MissingPortMatching(connection.getLoc))
+ else
+ Right(())
+ }
}
yield connection
@@ -188,30 +205,6 @@ object Connection {
}
}
- case class ConnectionMatching(
- isUnmatched: Boolean
- ) {
-
- def checkMatchingPorts(from: Connection.Endpoint, to: Connection.Endpoint): Result.Result[Unit] = {
- def checkMatch(pml: List[Component.PortMatching], pi: PortInstance): Result.Result[Unit] =
- if(pml.exists(pm => pi.equals(pm.instance1) || pi.equals(pm.instance2))) then Right(())
- else Left(SemanticError.MissingPortMatching(pi.getLoc))
-
- val fromPi = from.port.portInstance
- val toPi = to.port.portInstance
- val fromPml = from.port.componentInstance.component.portMatchingList
- val toPml = to.port.componentInstance.component.portMatchingList
-
- if(fromPml.isEmpty & toPml.isEmpty) then Left(SemanticError.MissingPortMatching(from.loc))
- else {
- for {
- _ <- if(!fromPml.isEmpty) then checkMatch(fromPml, fromPi) else Right(())
- _ <- if(!toPml.isEmpty) then checkMatch(toPml, toPi) else Right(())
- } yield Right(())
- }
- }
- }
-
object Endpoint {
/** Constructs a connection endpoint from AST info */
@@ -229,26 +222,6 @@ object Connection {
case None => Right(())
}
} yield endpoint
-
- }
-
- object ConnectionMatching {
-
- def fromAst(
- connectionMatchingAst: Ast.ConnectionMatching,
- from: Connection.Endpoint,
- to: Connection.Endpoint
- ): Result.Result[ConnectionMatching] = for {
- connectionMatching <- connectionMatchingAst match {
- case Ast.ConnectionMatching.Unmatched => Right(ConnectionMatching(true))
- case _ => Right(ConnectionMatching(false))
- }
- _ <- {
- if(connectionMatching.isUnmatched) then connectionMatching.checkMatchingPorts(from, to)
- else Right(())
- }
- } yield connectionMatching
-
}
}
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala
index 065904400..da67a1494 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/MatchedPortNumbering.scala
@@ -161,7 +161,7 @@ object MatchedPortNumbering {
val pii = PortInstanceIdentifier(ci, pi)
val cs = t.getConnectionsAt(pii).toList.sorted
Result.foldLeft (cs) (empty) ((m, c) => {
- if(c.connectionMatching.isUnmatched)
+ if(c.isUnmatched)
Right(m)
else {
val piiRemote = c.getOtherEndpoint(pi).port
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
index da95d3790..f8cb0a2de 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
@@ -108,7 +108,7 @@ object PatternResolver {
) = {
val from = Connection.Endpoint(loc, fromPii)
val to = Connection.Endpoint(loc, toPii)
- Connection(Connection.ConnectionMatching(false), from, to)
+ Connection(false, from, to)
}
private def missingPort[T](
diff --git a/compiler/lib/src/main/scala/ast/Ast.scala b/compiler/lib/src/main/scala/ast/Ast.scala
index 085481776..b583d3431 100644
--- a/compiler/lib/src/main/scala/ast/Ast.scala
+++ b/compiler/lib/src/main/scala/ast/Ast.scala
@@ -374,7 +374,7 @@ object Ast {
/** Connection */
final case class Connection(
- connectionMatching: ConnectionMatching,
+ isUnmatched: Boolean,
fromPort: AstNode[PortInstanceIdentifier],
fromIndex: Option[AstNode[Expr]],
toPort: AstNode[PortInstanceIdentifier],
@@ -706,14 +706,4 @@ object Ast {
override def toString = "public"
}
}
-
- sealed trait ConnectionMatching
- object ConnectionMatching {
- case object Unmatched extends ConnectionMatching {
- override def toString = "unmatched"
- }
- case object PossiblyMatched extends ConnectionMatching {
- override def toString = "possibly matched"
- }
- }
}
diff --git a/compiler/lib/src/main/scala/codegen/AstWriter.scala b/compiler/lib/src/main/scala/codegen/AstWriter.scala
index 843223eb5..c08c060bd 100644
--- a/compiler/lib/src/main/scala/codegen/AstWriter.scala
+++ b/compiler/lib/src/main/scala/codegen/AstWriter.scala
@@ -270,7 +270,7 @@ object AstWriter extends AstVisitor with LineUtils {
) = {
def direct(g: Ast.SpecConnectionGraph.Direct) = {
def connection(c: Ast.SpecConnectionGraph.Connection) = {
- lines("connection") ++ (
+ lines(if c.isUnmatched then "unmatched connection" else "connection") ++ (
addPrefix("from port", portInstanceIdentifier) (c.fromPort.data) ++
linesOpt(addPrefix("index", exprNode), c.fromIndex) ++
addPrefix("to port", portInstanceIdentifier) (c.toPort.data) ++
diff --git a/compiler/lib/src/main/scala/codegen/FppWriter.scala b/compiler/lib/src/main/scala/codegen/FppWriter.scala
index 3d24bfd5e..499263f47 100644
--- a/compiler/lib/src/main/scala/codegen/FppWriter.scala
+++ b/compiler/lib/src/main/scala/codegen/FppWriter.scala
@@ -617,10 +617,11 @@ object FppWriter extends AstVisitor with LineUtils {
addSuffix(s".${ident(pii.portName.data)}")
private def connection(c: Ast.SpecConnectionGraph.Connection) =
- portInstanceId(c.fromPort.data).
- joinOpt (c.fromIndex) ("") (bracketExprNode).
- join (" -> ") (portInstanceId(c.toPort.data)).
- joinOpt (c.toIndex) ("") (bracketExprNode)
+ lines(if c.isUnmatched then "unmatched " else "").
+ join ("") (portInstanceId(c.fromPort.data)).
+ joinOpt (c.fromIndex) ("") (bracketExprNode).
+ join (" -> ") (portInstanceId(c.toPort.data)).
+ joinOpt (c.toIndex) ("") (bracketExprNode)
private def typeNameNode(node: AstNode[Ast.TypeName]) = matchTypeNameNode((), node)
@@ -714,6 +715,7 @@ object FppWriter extends AstVisitor with LineUtils {
"topology",
"true",
"type",
+ "unmatched",
"update",
"warning",
"with",
diff --git a/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala b/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala
index d5b710ae7..7423ec3fc 100644
--- a/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala
+++ b/compiler/lib/src/main/scala/codegen/XmlFppWriter/TopologyXmlFppWriter.scala
@@ -129,7 +129,7 @@ object TopologyXmlFppWriter extends LineUtils {
}
yield {
Ast.SpecConnectionGraph.Connection(
- Ast.ConnectionMatching.PossiblyMatched,
+ false,
from._1,
from._2,
to._1,
diff --git a/compiler/lib/src/main/scala/syntax/Parser.scala b/compiler/lib/src/main/scala/syntax/Parser.scala
index 9df852482..4026e867a 100644
--- a/compiler/lib/src/main/scala/syntax/Parser.scala
+++ b/compiler/lib/src/main/scala/syntax/Parser.scala
@@ -49,7 +49,7 @@ object Parser extends Parsers {
opt(unmatched) ~! connectionPort ~! (rarrow ~>! connectionPort) ^^ {
case unmatched ~ (fromPort ~ fromIndex) ~ (toPort ~ toIndex) => {
Ast.SpecConnectionGraph.Connection(
- unmatched.getOrElse(Ast.ConnectionMatching.PossiblyMatched),
+ unmatched.isDefined,
fromPort,
fromIndex,
toPort,
@@ -914,7 +914,7 @@ object Parser extends Parsers {
private def typeToken = accept("type", { case t : Token.TYPE => t })
- private def unmatched = accept("unmatched", { case t : Token.UNMATCHED => Ast.ConnectionMatching.Unmatched })
+ private def unmatched = accept("unmatched", { case t : Token.UNMATCHED => t })
private def update = accept("update", { case t : Token.UPDATE => t })
diff --git a/docs/README.adoc b/docs/README.adoc
index 39e6acd2a..54ff2a773 100644
--- a/docs/README.adoc
+++ b/docs/README.adoc
@@ -11,11 +11,3 @@ system:
Once you have these tools installed, you can run `redo` in this directory
to regenerate the HTML files from the AsciiDoc source files.
-
-
-== Adding Keywords to FPP Specification
-. To add a new FPP keyword, first update the Lexical Elements section of the FPP spec.
-. Next, update the `doc/code-prettify/run_prettify.js` file so it includes the new keyword.
-Doing this will add syntax highlighting to the keyword in the FPP spec.
-. Finally, update `editors/emacs/fpp-mode.el` and `editors/vim/fpp.vim` so the emacs and vim
-editors syntax highlighting for the new keyword.
\ No newline at end of file
From a04f484ce10a29fd50462336ec5edb91b5dfe473 Mon Sep 17 00:00:00 2001
From: jawest
Date: Thu, 19 Sep 2024 13:52:05 -0700
Subject: [PATCH 06/73] added unit tests, cleanup
---
.../scala/analysis/Semantics/Connection.scala | 18 +++---
.../ResolveTopology/PatternResolver.scala | 2 +-
compiler/lib/src/main/scala/util/Error.scala | 2 +-
.../invalid_unmatched_connection.fpp | 31 ++++++++++
.../invalid_unmatched_connection.ref.txt | 5 ++
.../fpp-check/test/connection_direct/ok.fpp | 17 ++++++
.../fpp-check/test/connection_direct/tests.sh | 1 +
.../tools/fpp-format/test/include.ref.txt | 2 +
.../tools/fpp-format/test/no_include.ref.txt | 2 +
compiler/tools/fpp-format/test/syntax.fpp | 6 +-
.../tools/fpp-syntax/test/syntax-ast.ref.txt | 8 +++
.../test/syntax-include-ast.ref.txt | 8 +++
.../fpp-syntax/test/syntax-stdin.ref.txt | 8 +++
compiler/tools/fpp-syntax/test/syntax.fpp | 6 +-
.../unmatched/C1ComponentAi.ref.xml | 16 +++++
.../unmatched/C2ComponentAi.ref.xml | 16 +++++
.../top_numbering/unmatched/PPortAi.ref.xml | 8 +++
.../unmatched/TTopologyAppAi.ref.xml | 60 +++++++++++++++++++
.../test/top_numbering/unmatched/check-xml | 5 ++
.../test/top_numbering/unmatched/clean | 5 ++
.../test/top_numbering/unmatched/run | 5 ++
.../test/top_numbering/unmatched/run.sh | 5 ++
.../test/top_numbering/unmatched/tests.sh | 3 +
.../unmatched/unmatched_connections.fpp | 59 ++++++++++++++++++
.../unmatched/unmatched_connections.ref.txt | 0
.../test/top_numbering/unmatched/update-ref | 5 ++
.../top_numbering/unmatched/update-ref.sh | 5 ++
27 files changed, 294 insertions(+), 14 deletions(-)
create mode 100644 compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.fpp
create mode 100644 compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.ref.txt
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C1ComponentAi.ref.xml
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C2ComponentAi.ref.xml
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/PPortAi.ref.xml
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/TTopologyAppAi.ref.xml
create mode 100755 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/check-xml
create mode 100755 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/clean
create mode 100755 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run.sh
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/tests.sh
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/unmatched_connections.fpp
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/unmatched_connections.ref.txt
create mode 100755 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref
create mode 100644 compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref.sh
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala b/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
index 9af4c027a..b84251d52 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/Connection.scala
@@ -5,11 +5,11 @@ import fpp.compiler.util._
/** An FPP connection */
case class Connection(
- isUnmatched: Boolean,
/** The from endpoint */
from: Connection.Endpoint,
/** The to endpoint */
- to: Connection.Endpoint
+ to: Connection.Endpoint,
+ isUnmatched: Boolean = false
) extends Ordered[Connection] {
override def toString = s"${from.toString} -> ${to.toString}"
@@ -104,7 +104,7 @@ case class Connection(
}
}
- def checkMatchConstraint: Boolean = {
+ def isMatchConstrained: Boolean = {
def portMatchingExists(pml: List[Component.PortMatching], pi: PortInstance): Boolean =
pml.exists(pm => pi.equals(pm.instance1) || pi.equals(pm.instance2))
@@ -154,16 +154,14 @@ object Connection {
for {
from <- Endpoint.fromAst(a, connection.fromPort, connection.fromIndex)
to <- Endpoint.fromAst(a, connection.toPort, connection.toIndex)
- connection <- Right(Connection(connection.isUnmatched, from, to))
+ connection <- Right(Connection(from, to, connection.isUnmatched))
_ <- connection.checkDirections
_ <- connection.checkTypes
_ <- connection.checkSerialWithTypedInput
- _ <- {
- if !connection.checkMatchConstraint & connection.isUnmatched then
- Left(SemanticError.MissingPortMatching(connection.getLoc))
- else
- Right(())
- }
+ _ <-
+ if !connection.isMatchConstrained && connection.isUnmatched
+ then Left(SemanticError.MissingPortMatching(connection.getLoc))
+ else Right(())
}
yield connection
diff --git a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
index f8cb0a2de..7c66be44d 100644
--- a/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
+++ b/compiler/lib/src/main/scala/analysis/Semantics/ResolveTopology/PatternResolver.scala
@@ -108,7 +108,7 @@ object PatternResolver {
) = {
val from = Connection.Endpoint(loc, fromPii)
val to = Connection.Endpoint(loc, toPii)
- Connection(false, from, to)
+ Connection(from, to)
}
private def missingPort[T](
diff --git a/compiler/lib/src/main/scala/util/Error.scala b/compiler/lib/src/main/scala/util/Error.scala
index f8ce44252..d6ff30be2 100644
--- a/compiler/lib/src/main/scala/util/Error.scala
+++ b/compiler/lib/src/main/scala/util/Error.scala
@@ -193,7 +193,7 @@ sealed trait Error {
Error.print (Some(loc)) ("no match for this connection")
printMatchingLoc(matchingLoc)
case SemanticError.MissingPortMatching(loc) =>
- Error.print (Some(loc)) ("unmatched connections must use port matching")
+ Error.print (Some(loc)) ("unmatched connection must go from or to a matched port")
case SemanticError.MissingPort(loc, specMsg, portMsg) =>
Error.print (Some(loc)) (s"component with $specMsg must have $portMsg")
case SemanticError.OverlappingIdRanges(
diff --git a/compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.fpp b/compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.fpp
new file mode 100644
index 000000000..a099472f6
--- /dev/null
+++ b/compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.fpp
@@ -0,0 +1,31 @@
+port P1
+port P2
+
+passive component C1 {
+
+ output port p1Out: [5] P1
+ sync input port p1In: [5] P1
+
+ output port p2Out: P2
+ sync input port p2In: P2
+
+}
+
+instance c1: C1 base id 0x100
+instance c2: C1 base id 0x200
+
+topology T {
+
+ instance c1
+ instance c2
+
+ connections P1 {
+ unmatched c1.p1Out[0] -> c2.p1In[0]
+ unmatched c1.p1Out -> c2.p1In
+ }
+
+ connections P2 {
+ c1.p2Out -> c2.p2In
+ }
+
+}
diff --git a/compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.ref.txt b/compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.ref.txt
new file mode 100644
index 000000000..0fcf6e1d7
--- /dev/null
+++ b/compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.ref.txt
@@ -0,0 +1,5 @@
+fpp-check
+[ local path prefix ]/compiler/tools/fpp-check/test/connection_direct/invalid_unmatched_connection.fpp:23.15
+ unmatched c1.p1Out[0] -> c2.p1In[0]
+ ^
+error: unmatched connection must go from or to a matched port
diff --git a/compiler/tools/fpp-check/test/connection_direct/ok.fpp b/compiler/tools/fpp-check/test/connection_direct/ok.fpp
index 7a2f66a7d..0ae1443b0 100644
--- a/compiler/tools/fpp-check/test/connection_direct/ok.fpp
+++ b/compiler/tools/fpp-check/test/connection_direct/ok.fpp
@@ -1,4 +1,6 @@
port P
+port P2
+
passive component C1 {
output port pOut: [2] P
output port serialOut: [2] serial
@@ -7,15 +9,30 @@ passive component C2 {
sync input port pIn: P
sync input port serialIn: serial
}
+
+passive component C3 {
+ output port pOut: [5] P2
+ sync input port pIn: [5] P2
+ match pOut with pIn
+}
+
instance c1: C1 base id 0x100
instance c2: C2 base id 0x200
+instance c3: C3 base id 0x300
+instance c4: C3 base id 0x400
+
topology T {
instance c1
instance c2
+ instance c3
+ instance c4
connections C {
c1.pOut -> c2.pIn
c1.serialOut -> c2.pIn
c1.pOut -> c2.serialIn
c1.serialOut -> c2.serialIn
+
+ unmatched c3.pOut[0] -> c4.pIn[0]
+ unmatched c3.pOut -> c4.pIn
}
}
diff --git a/compiler/tools/fpp-check/test/connection_direct/tests.sh b/compiler/tools/fpp-check/test/connection_direct/tests.sh
index e8f2c0690..3f5b34d7b 100644
--- a/compiler/tools/fpp-check/test/connection_direct/tests.sh
+++ b/compiler/tools/fpp-check/test/connection_direct/tests.sh
@@ -4,6 +4,7 @@ internal_port
invalid_directions
invalid_port_instance
invalid_port_number
+invalid_unmatched_connection
mismatched_port_types
ok
serial_to_typed_with_return
diff --git a/compiler/tools/fpp-format/test/include.ref.txt b/compiler/tools/fpp-format/test/include.ref.txt
index f417f168f..2d8e5b332 100644
--- a/compiler/tools/fpp-format/test/include.ref.txt
+++ b/compiler/tools/fpp-format/test/include.ref.txt
@@ -165,6 +165,8 @@ module DefinitionsAndSpecifiers {
@ Direct connection graph specifier
connections C {
i1.p[0] -> i2.p[1]
+ unmatched i1.p1[0] -> i2.p2[0]
+ unmatched i1.p1 -> i2.p2
} @< Direct connection graph specifier
@ Graph pattern specifier
diff --git a/compiler/tools/fpp-format/test/no_include.ref.txt b/compiler/tools/fpp-format/test/no_include.ref.txt
index c805ea27d..1340c0920 100644
--- a/compiler/tools/fpp-format/test/no_include.ref.txt
+++ b/compiler/tools/fpp-format/test/no_include.ref.txt
@@ -165,6 +165,8 @@ module DefinitionsAndSpecifiers {
@ Direct connection graph specifier
connections C {
i1.p[0] -> i2.p[1]
+ unmatched i1.p1[0] -> i2.p2[0]
+ unmatched i1.p1 -> i2.p2
} @< Direct connection graph specifier
@ Graph pattern specifier
diff --git a/compiler/tools/fpp-format/test/syntax.fpp b/compiler/tools/fpp-format/test/syntax.fpp
index 2b99a8f60..615113ef4 100644
--- a/compiler/tools/fpp-format/test/syntax.fpp
+++ b/compiler/tools/fpp-format/test/syntax.fpp
@@ -137,7 +137,11 @@ module DefinitionsAndSpecifiers {
@< Private instance specifier
@ Direct connection graph specifier
- connections C { i1.p[0] -> i2.p[1] }
+ connections C {
+ i1.p[0] -> i2.p[1]
+ unmatched i1.p1[0] -> i2.p2[0]
+ unmatched i1.p1 -> i2.p2
+ }
@< Direct connection graph specifier
@ Graph pattern specifier
diff --git a/compiler/tools/fpp-syntax/test/syntax-ast.ref.txt b/compiler/tools/fpp-syntax/test/syntax-ast.ref.txt
index e9b9c7547..42a82ad0a 100644
--- a/compiler/tools/fpp-syntax/test/syntax-ast.ref.txt
+++ b/compiler/tools/fpp-syntax/test/syntax-ast.ref.txt
@@ -275,6 +275,14 @@ def module
index literal int 0
to port qual ident i2.p
index literal int 1
+ unmatched connection
+ from port qual ident i1.p1
+ index literal int 0
+ to port qual ident i2.p2
+ index literal int 0
+ unmatched connection
+ from port qual ident i1.p1
+ to port qual ident i2.p2
@< Direct connection graph specifier
@ Graph pattern specifier
spec connection graph pattern
diff --git a/compiler/tools/fpp-syntax/test/syntax-include-ast.ref.txt b/compiler/tools/fpp-syntax/test/syntax-include-ast.ref.txt
index bdea0bad2..bfb368c7d 100644
--- a/compiler/tools/fpp-syntax/test/syntax-include-ast.ref.txt
+++ b/compiler/tools/fpp-syntax/test/syntax-include-ast.ref.txt
@@ -276,6 +276,14 @@ def module
index literal int 0
to port qual ident i2.p
index literal int 1
+ unmatched connection
+ from port qual ident i1.p1
+ index literal int 0
+ to port qual ident i2.p2
+ index literal int 0
+ unmatched connection
+ from port qual ident i1.p1
+ to port qual ident i2.p2
@< Direct connection graph specifier
@ Graph pattern specifier
spec connection graph pattern
diff --git a/compiler/tools/fpp-syntax/test/syntax-stdin.ref.txt b/compiler/tools/fpp-syntax/test/syntax-stdin.ref.txt
index bdea0bad2..bfb368c7d 100644
--- a/compiler/tools/fpp-syntax/test/syntax-stdin.ref.txt
+++ b/compiler/tools/fpp-syntax/test/syntax-stdin.ref.txt
@@ -276,6 +276,14 @@ def module
index literal int 0
to port qual ident i2.p
index literal int 1
+ unmatched connection
+ from port qual ident i1.p1
+ index literal int 0
+ to port qual ident i2.p2
+ index literal int 0
+ unmatched connection
+ from port qual ident i1.p1
+ to port qual ident i2.p2
@< Direct connection graph specifier
@ Graph pattern specifier
spec connection graph pattern
diff --git a/compiler/tools/fpp-syntax/test/syntax.fpp b/compiler/tools/fpp-syntax/test/syntax.fpp
index 2b99a8f60..615113ef4 100644
--- a/compiler/tools/fpp-syntax/test/syntax.fpp
+++ b/compiler/tools/fpp-syntax/test/syntax.fpp
@@ -137,7 +137,11 @@ module DefinitionsAndSpecifiers {
@< Private instance specifier
@ Direct connection graph specifier
- connections C { i1.p[0] -> i2.p[1] }
+ connections C {
+ i1.p[0] -> i2.p[1]
+ unmatched i1.p1[0] -> i2.p2[0]
+ unmatched i1.p1 -> i2.p2
+ }
@< Direct connection graph specifier
@ Graph pattern specifier
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C1ComponentAi.ref.xml b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C1ComponentAi.ref.xml
new file mode 100644
index 000000000..8a186df23
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C1ComponentAi.ref.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ PPortAi.xml
+
+
+
+
+
+
+
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C2ComponentAi.ref.xml b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C2ComponentAi.ref.xml
new file mode 100644
index 000000000..b875e5dc6
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/C2ComponentAi.ref.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ PPortAi.xml
+
+
+
+
+
+
+
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/PPortAi.ref.xml b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/PPortAi.ref.xml
new file mode 100644
index 000000000..64b132daf
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/PPortAi.ref.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/TTopologyAppAi.ref.xml b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/TTopologyAppAi.ref.xml
new file mode 100644
index 000000000..3eb2191a5
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/TTopologyAppAi.ref.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+ C1ComponentAi.xml
+ C2ComponentAi.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/check-xml b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/check-xml
new file mode 100755
index 000000000..50af24b01
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/check-xml
@@ -0,0 +1,5 @@
+#!/bin/sh -e
+
+export COMPILER_ROOT=$PWD/../../../../..
+
+sh ../../scripts/check-xml.sh
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/clean b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/clean
new file mode 100755
index 000000000..8d322fe40
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/clean
@@ -0,0 +1,5 @@
+#!/bin/sh -e
+
+export COMPILER_ROOT=../../../../..
+
+sh ../../scripts/clean.sh
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run
new file mode 100755
index 000000000..6bcb2b473
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+export COMPILER_ROOT=../../../../..
+
+sh ../../scripts/run.sh
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run.sh b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run.sh
new file mode 100644
index 000000000..a38d9a73d
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/run.sh
@@ -0,0 +1,5 @@
+numbering_matched()
+{
+ run_test "-p $PWD" unmatched_connections && \
+ diff_xml PPort C1Component C2Component TTopologyApp
+}
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/tests.sh b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/tests.sh
new file mode 100644
index 000000000..bdd8decc1
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/tests.sh
@@ -0,0 +1,3 @@
+tests="
+unmatched_connections
+"
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/unmatched_connections.fpp b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/unmatched_connections.fpp
new file mode 100644
index 000000000..30d413f88
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/unmatched_connections.fpp
@@ -0,0 +1,59 @@
+module M {
+
+ port P
+
+ passive component C1 {
+
+ output port pOut: [6] P
+ sync input port pIn: [6] P
+
+ match pOut with pIn
+ }
+
+ passive component C2 {
+
+ output port pOut: [6] P
+ sync input port pIn: [6] P
+
+ match pOut with pIn
+ }
+
+ instance c1: C1 base id 0x100
+ instance c2: C1 base id 0x200
+ instance c3: C2 base id 0x300
+ instance c4: C2 base id 0x400
+
+ topology T {
+
+ instance c1
+ instance c2
+ instance c3
+ instance c4
+
+ connections P {
+ # Case 1: 2 ports that go to the same component
+ unmatched c1.pOut -> c1.pIn
+ unmatched c2.pOut -> c1.pIn
+ unmatched c3.pOut -> c3.pIn
+ unmatched c4.pOut -> c4.pIn
+
+ # Case 2: Have a connection out of A at some index i and
+ # some connection at B at same index i but they go to different components
+ unmatched c1.pOut[1] -> c1.pIn[1]
+ unmatched c2.pOut[1] -> c2.pIn[1]
+
+
+ # Case 3: Have a connection out of A at index i and
+ # some connection at B index at j not equal to i going to same component
+ unmatched c3.pOut[2] -> c3.pIn[2]
+ unmatched c4.pOut[3] -> c3.pIn[3]
+
+ # Case 4: Have a connection out of A at index i and
+ # some connection at B index at j not equal to i going to different component
+ unmatched c3.pOut[4] -> c3.pIn[4]
+ unmatched c4.pOut[5] -> c4.pIn[5]
+
+ }
+ }
+
+}
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/unmatched_connections.ref.txt b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/unmatched_connections.ref.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref
new file mode 100755
index 000000000..2889a0733
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+export COMPILER_ROOT=../../../../..
+
+sh ../../scripts/update-ref.sh
diff --git a/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref.sh b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref.sh
new file mode 100644
index 000000000..ad8ab30d7
--- /dev/null
+++ b/compiler/tools/fpp-to-xml/test/top_numbering/unmatched/update-ref.sh
@@ -0,0 +1,5 @@
+numbering_matched()
+{
+ update "-p $PWD" unmatched_connections
+ move_xml PPort C1Component C2Component TTopologyApp
+}
From 1ee946a906eb66ebcf8a5cb1ed5a169c11068547 Mon Sep 17 00:00:00 2001
From: jawest
Date: Thu, 19 Sep 2024 18:07:46 -0700
Subject: [PATCH 07/73] update user guide
---
docs/users-guide/Defining-Topologies.adoc | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/docs/users-guide/Defining-Topologies.adoc b/docs/users-guide/Defining-Topologies.adoc
index 2b5f3f7b5..6d0adbb65 100644
--- a/docs/users-guide/Defining-Topologies.adoc
+++ b/docs/users-guide/Defining-Topologies.adoc
@@ -27,8 +27,9 @@ fit together.
port P
passive component C {
- sync input port pIn: P
- output port pOut: P
+ sync input port pIn: [3] P
+ output port pOut: [3] P
+ match pOut with pIn
}
instance c1: C base id 0x100
@@ -45,6 +46,8 @@ topology Simple {
@ This code specifies a connection graph C1
connections C1 {
c1.pOut -> c2.pIn
+ unmatched c1.pOut[1] -> c2.pIn[1]
+ unmatched c1.pOut[2] -> c2.pIn[2]
}
@ This code specifies a connection graph C2
@@ -58,6 +61,7 @@ topology Simple {
In this example, we define a <> `P`.
Then we define a <> `C`
with an input port and an output port, both of type `P`.
+We specify that the output port and the input port are matched.
We define two <> of
`C`, `c1` and `c2`.
We put these instances into a topology called `Simple`.
@@ -113,10 +117,13 @@ An endpoint is the name of a component instance
(which in general may be a qualified name), a dot,
and the name of a port of that component instance.
-In this example there are two connection graphs, each containing
-one connection:
+In this example there are two connection graphs:
+
+. A connection graph `C1` containing:
+.. A connection from `c1.pOut` to `c2.pIn`.
+.. An unmatched connection from `c1.pOut[1]` to `c2.pIn[1]`
+.. An unmatched connection from `c1.pOut[2]` to `c2.pIn[2]`
-. A connection graph `C1` containing a connection from `c1.pOut` to `c2.pIn`.
. A connection graph `C2` containing a connection from `c2.pOut` to `c1.pIn`.
@@ -242,6 +249,8 @@ In particular, serial to serial connections are allowed.
then the port type of _P_ may not specify a
<>.
+* `unmatched` specifiers must only be specified on connections that are match constrained.
+
==== Pattern Graph Specifiers
A few connection patterns are so common in F Prime that they
@@ -699,7 +708,7 @@ When you use matched numbering with direct graph specifiers, you
must obey the following rules:
. When a component has the matching specifier
-`match p1 with p2`, for every connection between `p1`
+`match p1 with p2`, for every matched connection between `p1`
and another component, there must be a corresponding
connection between that other component and `p2`.
From 5f8c36501ee372ae999fd80b0f5a3513200cb673 Mon Sep 17 00:00:00 2001
From: jawest
Date: Tue, 24 Sep 2024 15:49:46 -0700
Subject: [PATCH 08/73] revert doc changes
---
docs/fpp-spec.html | 2 +-
docs/fpp-users-guide.html | 20 ++++++++++----------
docs/index.html | 7 ++++---
docs/users-guide/Defining-Topologies.adoc | 15 ++++-----------
4 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html
index a8dead3d8..a5ee716f0 100644
--- a/docs/fpp-spec.html
+++ b/docs/fpp-spec.html
@@ -9801,7 +9801,7 @@
port P
passive component C {
- sync input port pIn: P
- output port pOut: P
+ sync input port pIn: [3] P
+ output port pOut: [3] P
}
instance c1: C base id 0x100
@@ -7717,14 +7718,13 @@
12.1. A Simple Example
In this example there are two connection graphs, each containing
-one connection:
+one connection:
+. A connection graph C1 containing:
+. A connection from c1.pOut to c2.pIn.
-
A connection graph C1 containing a connection from c1.pOut to c2.pIn.
-
-
A connection graph C2 containing a connection from c2.pOut to c1.pIn.
@@ -8396,7 +8396,7 @@
12.3.2. Matched Nu
When a component has the matching specifier
-match p1 with p2, for every connection between p1
+match p1 with p2, for every matched connection between p1
and another component, there must be a corresponding
connection between that other component and p2.