From a06732b6e378c60e7a593be5bcd07c49910b11ce Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Fri, 23 Oct 2026 16:14:19 -0700 Subject: [PATCH 1/8] Revise dependency algorithm --- .../ComputeDependencies/AddDependencies.scala | 2 +- docs/wiki/Computing-Dependencies.asciidoc | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala index 59ea43cf6..ff87b8708 100644 --- a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala +++ b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala @@ -174,7 +174,7 @@ object AddDependencies private def addDependencies (a: Analysis) (specLoc: Ast.SpecLoc): Result = { val file = getFile(specLoc) - if !a.inputFileSet.contains(file) && !a.dependencyFileSet.contains(file) + if !a.inputFileSet.contains(file) && ((a.level == 1) || !a.dependencyFileSet.contains(file)) then addDependenciesHelper(a, specLoc, file) else Right(a) } diff --git a/docs/wiki/Computing-Dependencies.asciidoc b/docs/wiki/Computing-Dependencies.asciidoc index 3f8646b3f..5b055a61d 100644 --- a/docs/wiki/Computing-Dependencies.asciidoc +++ b/docs/wiki/Computing-Dependencies.asciidoc @@ -6,6 +6,7 @@ This algorithm computes dependencies for a list of translation units. _a_. The https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[input file set] of _a_ must record the set of files presented for analysis. +The level must be zero, and the scope name list must be empty. . A list _tul_ of FPP translation units. @@ -30,12 +31,14 @@ Run the <> on _tul_. To run the dependency algorithm on a translation unit list _tul_, do the following: +. *Increment the level:* Increment the level in _a_. + . *Resolve include specifiers:* Recursively resolve include specifiers in _tul_. Add the path of each included file to the included file set in _a_. If the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[level of _a_] -is zero, then add the path of each included file to the direct dependency +is one, then add the path of each included file to the direct dependency file set in _a_. . *Build the location specifier map:* Traverse each translation unit _tu_ in @@ -133,6 +136,8 @@ file set, if _f_ appears in the dependency file set, then delete it from the set. The dependency is already recorded in the file that includes _f_. +. *Decrement the level:* Decrement the level in _a_. + [[adding-dependencies]] === Adding Dependencies for a Location Specifier @@ -142,13 +147,15 @@ To add a dependency for a location specifier _s_, do the following: . If _p_ is in the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[input file set] -of _a_ or is already in the +of _a_, then do nothing. + +. Otherwise if the level of _a_ is not one, and _p_ is already in the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency file set] of _a_, then do nothing. . Otherwise -.. If the level of _a_ is zero, then add _p_ to the +.. If the level of _a_ is one, then add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[direct dependency file set] of _a_. @@ -170,8 +177,7 @@ translation unit map] of _a_. ... Run the <> on the list _[ tu ]_ with the value of _a_ computed so far, but with an empty scope name list. -Restore the current level and scope name list and -let the result be the new _a_. +Restore the current scope name list and let the result be the new _a_. .. Otherwise add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[missing From 2617959ffe123f777a92b6699906ae2eb0f04f44 Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Fri, 23 Oct 2026 16:36:04 -0700 Subject: [PATCH 2/8] Revise fpp-depend tests --- compiler/tools/fpp-depend/test/direct_already_seen.fpp | 9 +++++++++ .../tools/fpp-depend/test/direct_already_seen.ref.txt | 2 ++ compiler/tools/fpp-depend/test/direct_already_seen_a.fpp | 1 + compiler/tools/fpp-depend/test/direct_already_seen_b.fpp | 1 + .../fpp-depend/test/direct_already_seen_output.ref.txt | 2 ++ compiler/tools/fpp-depend/test/run | 9 +++++++++ compiler/tools/fpp-depend/test/tests.sh | 1 + compiler/tools/fpp-depend/test/update-ref | 5 +++++ 8 files changed, 30 insertions(+) create mode 100644 compiler/tools/fpp-depend/test/direct_already_seen.fpp create mode 100644 compiler/tools/fpp-depend/test/direct_already_seen.ref.txt create mode 100644 compiler/tools/fpp-depend/test/direct_already_seen_a.fpp create mode 100644 compiler/tools/fpp-depend/test/direct_already_seen_b.fpp create mode 100644 compiler/tools/fpp-depend/test/direct_already_seen_output.ref.txt diff --git a/compiler/tools/fpp-depend/test/direct_already_seen.fpp b/compiler/tools/fpp-depend/test/direct_already_seen.fpp new file mode 100644 index 000000000..e4eebdff8 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen.fpp @@ -0,0 +1,9 @@ +# Test direct dependencies already seen at a lower level +# The dependency on b exists in direct_already_seen_a.fpp at level 2 +# But it should be reported here as a direct dependency + +locate constant a at "direct_already_seen_a.fpp" +locate constant b at "direct_already_seen_b.fpp" + +constant c = a +constant d = b diff --git a/compiler/tools/fpp-depend/test/direct_already_seen.ref.txt b/compiler/tools/fpp-depend/test/direct_already_seen.ref.txt new file mode 100644 index 000000000..7bd3847e0 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen.ref.txt @@ -0,0 +1,2 @@ +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp diff --git a/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp b/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp new file mode 100644 index 000000000..84b672789 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp @@ -0,0 +1 @@ +constant a = b diff --git a/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp b/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp new file mode 100644 index 000000000..94da10dfe --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp @@ -0,0 +1 @@ +constant b = 0 \ No newline at end of file diff --git a/compiler/tools/fpp-depend/test/direct_already_seen_output.ref.txt b/compiler/tools/fpp-depend/test/direct_already_seen_output.ref.txt new file mode 100644 index 000000000..7bd3847e0 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen_output.ref.txt @@ -0,0 +1,2 @@ +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp diff --git a/compiler/tools/fpp-depend/test/run b/compiler/tools/fpp-depend/test/run index 985105647..bd267f951 100755 --- a/compiler/tools/fpp-depend/test/run +++ b/compiler/tools/fpp-depend/test/run @@ -47,6 +47,15 @@ direct() test $run_test_status -eq 0 } +direct_already_seen() +{ + run_test '-d tmp.out.txt' direct_already_seen + run_test_status=$? + remove_path_prefix < tmp.out.txt > direct_already_seen_output.out.txt + compare direct_already_seen_output && \ + test $run_test_status -eq 0 +} + filenames() { run_test '-g filenames_generated_output.out.txt -u filenames_ut_output.out.txt' \ diff --git a/compiler/tools/fpp-depend/test/tests.sh b/compiler/tools/fpp-depend/test/tests.sh index bc08b1fbd..dec1d36d1 100644 --- a/compiler/tools/fpp-depend/test/tests.sh +++ b/compiler/tools/fpp-depend/test/tests.sh @@ -12,6 +12,7 @@ def_system dictionary dictionary_no_deployment_top direct +direct_already_seen enum_constant expr_array expr_binop diff --git a/compiler/tools/fpp-depend/test/update-ref b/compiler/tools/fpp-depend/test/update-ref index 4565616f1..db746d5cf 100755 --- a/compiler/tools/fpp-depend/test/update-ref +++ b/compiler/tools/fpp-depend/test/update-ref @@ -42,6 +42,11 @@ direct() { remove_path_prefix < tmp.out.txt > direct_output.ref.txt } +direct_already_seen() { + update '-d tmp.out.txt' direct_already_seen + remove_path_prefix < tmp.out.txt > direct_already_seen_output.ref.txt +} + filenames() { update '-g filenames_generated_output.ref.txt -u filenames_ut_output.ref.txt' \ ../../fpp-filenames/test/ok filenames From f882930f99872a007c11adc251394037956b6967 Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Fri, 23 Oct 2026 20:13:24 -0700 Subject: [PATCH 3/8] Revise Computing Dependencies algorithm --- docs/wiki/Computing-Dependencies.asciidoc | 28 +++++++++++------------ 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/docs/wiki/Computing-Dependencies.asciidoc b/docs/wiki/Computing-Dependencies.asciidoc index 5b055a61d..2190d91d4 100644 --- a/docs/wiki/Computing-Dependencies.asciidoc +++ b/docs/wiki/Computing-Dependencies.asciidoc @@ -145,40 +145,38 @@ To add a dependency for a location specifier _s_, do the following: . Compute the absolute path _p_ associated with _s_. -. If _p_ is in the +. If _p_ is not in the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[input file set] -of _a_, then do nothing. - -. Otherwise if the level of _a_ is not one, and _p_ is already in the -https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency file set] -of _a_, then do nothing. - -. Otherwise +of _a_, then .. If the level of _a_ is one, then add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[direct dependency file set] of _a_. -.. Add _p_ to the +.. If _p_ is not already in the +https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency file set] +of _a_, then + +... Add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency file set] of _a_. -.. If the file _f_ at _p_ exists, then +... If the file _f_ at _p_ exists, then -... Parse _f_, generating a translation unit _tu_. +.... Parse _f_, generating a translation unit _tu_. -... Recursively resolve include specifiers in _tu_. +.... Recursively resolve include specifiers in _tu_. Add the path of each included file to the included file set in _a_. -... Add the mapping from _p_ to _tu_ to the +.... Add the mapping from _p_ to _tu_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency translation unit map] of _a_. -... Run the <> on the list _[ tu ]_ +.... Run the <> on the list _[ tu ]_ with the value of _a_ computed so far, but with an empty scope name list. Restore the current scope name list and let the result be the new _a_. -.. Otherwise add _p_ to the +... Otherwise add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[missing dependency file set] of _a_. From 89b20e085fd03166f2c73486dccb5f689ee1b07f Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Fri, 23 Oct 2026 21:01:30 -0700 Subject: [PATCH 4/8] Revise AddDependencies --- .../ComputeDependencies/AddDependencies.scala | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala index ff87b8708..94d60bf30 100644 --- a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala +++ b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala @@ -142,16 +142,9 @@ object AddDependencies isAbsolute ).map(addDependencies (a)).getOrElse(Right(a)) - private def addDependenciesHelper(a: Analysis, specLoc: Ast.SpecLoc, file: File): Result = { + private def updateDependencyFileSet(a: Analysis, file: File): Result = { val dependencyFileSet = a.dependencyFileSet + file - val directDependencyFileSet = a.level match { - case 1 => a.directDependencyFileSet + file - case _ => a.directDependencyFileSet - } - val a1 = a.copy( - dependencyFileSet = dependencyFileSet, - directDependencyFileSet = directDependencyFileSet - ) + val a1 = a.copy(dependencyFileSet = dependencyFileSet) val result = for { tu <- Parser.parseFile (Parser.transUnit) (None) (file) pair <- ResolveSpecInclude.transUnit(a1, tu) @@ -172,10 +165,21 @@ object AddDependencies } } + private def updateDirectDependencyFileSet(a: Analysis, file: File) = + a.level match { + case 1 => a.copy(directDependencyFileSet = a.directDependencyFileSet + file) + case _ => a + } + private def addDependencies (a: Analysis) (specLoc: Ast.SpecLoc): Result = { val file = getFile(specLoc) - if !a.inputFileSet.contains(file) && ((a.level == 1) || !a.dependencyFileSet.contains(file)) - then addDependenciesHelper(a, specLoc, file) + if !a.inputFileSet.contains(file) + then + for { + a <- Right(updateDirectDependencyFileSet(a, file)) + a <- if !a.dependencyFileSet.contains(file) then updateDependencyFileSet(a, file) else Right(a) + } + yield a else Right(a) } From ad8b5bc106853838cd04ed2315afde72585e7a68 Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Fri, 23 Oct 2026 21:18:43 -0700 Subject: [PATCH 5/8] Revise AddDependencies --- .../ComputeDependencies/AddDependencies.scala | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala index 94d60bf30..04ccbec1a 100644 --- a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala +++ b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala @@ -142,32 +142,35 @@ object AddDependencies isAbsolute ).map(addDependencies (a)).getOrElse(Right(a)) - private def updateDependencyFileSet(a: Analysis, file: File): Result = { - val dependencyFileSet = a.dependencyFileSet + file - val a1 = a.copy(dependencyFileSet = dependencyFileSet) - val result = for { - tu <- Parser.parseFile (Parser.transUnit) (None) (file) - pair <- ResolveSpecInclude.transUnit(a1, tu) - a2 <- ComputeDependencies.tuList( - pair._1.copy( - scopeNameList = Nil, - dependencyTuMap = pair._1.dependencyTuMap + (file -> pair._2) - ), - List(pair._2) - ) - } yield a2.copy(scopeNameList = a1.scopeNameList) - result match { - case Left(FileError.CannotOpen(_, _)) => { - val a = a1.copy(missingDependencyFileSet = a1.missingDependencyFileSet + file) - Right(a) + private def updateDependencyFileSet(a: Analysis, file: File): Result = + if !a.dependencyFileSet.contains(file) then + val dependencyFileSet = a.dependencyFileSet + file + val a1 = a.copy(dependencyFileSet = dependencyFileSet) + val result = for { + tu <- Parser.parseFile (Parser.transUnit) (None) (file) + (a2, tu) <- ResolveSpecInclude.transUnit(a1, tu) + a3 <- ComputeDependencies.tuList( + a2.copy( + scopeNameList = Nil, + dependencyTuMap = a2.dependencyTuMap + (file -> tu) + ), + List(tu) + ) + } yield a3.copy(scopeNameList = a1.scopeNameList) + result match { + case Left(FileError.CannotOpen(_, _)) => { + val missingDependencyFileSet = a1.missingDependencyFileSet + file + Right(a1.copy(missingDependencyFileSet = missingDependencyFileSet)) + } + case _ => result } - case _ => result - } - } + else Right(a) private def updateDirectDependencyFileSet(a: Analysis, file: File) = a.level match { - case 1 => a.copy(directDependencyFileSet = a.directDependencyFileSet + file) + case 1 => + val directDependencyFileSet = a.directDependencyFileSet + file + a.copy(directDependencyFileSet = directDependencyFileSet) case _ => a } @@ -177,7 +180,7 @@ object AddDependencies then for { a <- Right(updateDirectDependencyFileSet(a, file)) - a <- if !a.dependencyFileSet.contains(file) then updateDependencyFileSet(a, file) else Right(a) + a <- updateDependencyFileSet(a, file) } yield a else Right(a) From 8da85b6ce213b605a71d4d273775d92b6e570f14 Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Mon, 26 Oct 2026 09:55:42 -0700 Subject: [PATCH 6/8] Refactor AddDependencies --- .../ComputeDependencies/AddDependencies.scala | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala index 04ccbec1a..cf762104a 100644 --- a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala +++ b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala @@ -142,47 +142,46 @@ object AddDependencies isAbsolute ).map(addDependencies (a)).getOrElse(Right(a)) - private def updateDependencyFileSet(a: Analysis, file: File): Result = - if !a.dependencyFileSet.contains(file) then - val dependencyFileSet = a.dependencyFileSet + file - val a1 = a.copy(dependencyFileSet = dependencyFileSet) - val result = for { - tu <- Parser.parseFile (Parser.transUnit) (None) (file) - (a2, tu) <- ResolveSpecInclude.transUnit(a1, tu) - a3 <- ComputeDependencies.tuList( - a2.copy( - scopeNameList = Nil, - dependencyTuMap = a2.dependencyTuMap + (file -> tu) - ), - List(tu) - ) - } yield a3.copy(scopeNameList = a1.scopeNameList) - result match { - case Left(FileError.CannotOpen(_, _)) => { - val missingDependencyFileSet = a1.missingDependencyFileSet + file - Right(a1.copy(missingDependencyFileSet = missingDependencyFileSet)) - } - case _ => result + private def addDependenciesForFile(a: Analysis, file: File): Result = + val result = for { + tu <- Parser.parseFile (Parser.transUnit) (None) (file) + (a2, tu) <- ResolveSpecInclude.transUnit(a, tu) + a3 <- ComputeDependencies.tuList( + a2.copy( + scopeNameList = Nil, + dependencyTuMap = a2.dependencyTuMap + (file -> tu) + ), + List(tu) + ) + } yield a3.copy(scopeNameList = a.scopeNameList) + result match { + case Left(FileError.CannotOpen(_, _)) => { + val missingDependencyFileSet = a.missingDependencyFileSet + file + Right(a.copy(missingDependencyFileSet = missingDependencyFileSet)) } - else Right(a) + case _ => result + } private def updateDirectDependencyFileSet(a: Analysis, file: File) = - a.level match { - case 1 => - val directDependencyFileSet = a.directDependencyFileSet + file - a.copy(directDependencyFileSet = directDependencyFileSet) - case _ => a - } + val directDependencyFileSet = a.directDependencyFileSet + file + a.copy(directDependencyFileSet = directDependencyFileSet) + + private def updateDependencyFileSet(a: Analysis, file: File) = + val dependencyFileSet = a.dependencyFileSet + file + a.copy(dependencyFileSet = dependencyFileSet) private def addDependencies (a: Analysis) (specLoc: Ast.SpecLoc): Result = { val file = getFile(specLoc) if !a.inputFileSet.contains(file) then - for { - a <- Right(updateDirectDependencyFileSet(a, file)) - a <- updateDependencyFileSet(a, file) - } - yield a + val a1 = if a.level == 1 + then updateDirectDependencyFileSet(a, file) + else a + if !a1.dependencyFileSet.contains(file) + then + val a2 = updateDependencyFileSet(a1, file) + addDependenciesForFile(a2, file) + else Right(a1) else Right(a) } From 2f18f3316d4d7f6e33bce85615f0555a8eb9adfb Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Mon, 26 Oct 2026 10:08:51 -0700 Subject: [PATCH 7/8] Refactor AddDependencies --- .../ComputeDependencies/AddDependencies.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala index cf762104a..cd769f424 100644 --- a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala +++ b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala @@ -143,17 +143,18 @@ object AddDependencies ).map(addDependencies (a)).getOrElse(Right(a)) private def addDependenciesForFile(a: Analysis, file: File): Result = + val scopeNameList = a.scopeNameList val result = for { tu <- Parser.parseFile (Parser.transUnit) (None) (file) - (a2, tu) <- ResolveSpecInclude.transUnit(a, tu) - a3 <- ComputeDependencies.tuList( - a2.copy( + (a, tu) <- ResolveSpecInclude.transUnit(a, tu) + a <- ComputeDependencies.tuList( + a.copy( scopeNameList = Nil, - dependencyTuMap = a2.dependencyTuMap + (file -> tu) + dependencyTuMap = a.dependencyTuMap + (file -> tu) ), List(tu) ) - } yield a3.copy(scopeNameList = a.scopeNameList) + } yield a.copy(scopeNameList = scopeNameList) result match { case Left(FileError.CannotOpen(_, _)) => { val missingDependencyFileSet = a.missingDependencyFileSet + file From a99d84a49e8c3dbee0808e26bce6b31281d18eed Mon Sep 17 00:00:00 2001 From: Rob Bocchino Date: Mon, 26 Oct 2026 10:14:11 -0700 Subject: [PATCH 8/8] Add newline to end of file --- compiler/tools/fpp-depend/test/direct_already_seen_b.fpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp b/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp index 94da10dfe..da1487112 100644 --- a/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp +++ b/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp @@ -1 +1 @@ -constant b = 0 \ No newline at end of file +constant b = 0