Generate SSD learned example file loop from typed Jerboa

ober

788f303c276e492832b125e35d126c8d9682faf6

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 48ff30c..4e144fe 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -2089,7 +2089,7 @@
                 truthStoreMakePinnedTrustManager
                 zipEntryPresent
                 zipEntryIsDirectory zipEntryIsFile zipEntryDeclaresExcessiveSize
-                forEachFileArray
+                forEachFileArray forEachFileUntil
                 countInstalledStagedZipEntries)
         (type File)
         (type Path)
@@ -2126,6 +2126,16 @@
                 (invoke action (list-ref files i))
                 ignored))
             (begin)))
+        (def (forEachFileUntil
+               (files : (List File))
+               (action : (-> File Bool))) : Unit
+          (begin
+            (for/fold ((keepGoing #t))
+                      ((i (in-range (int32 0) (list-size files))))
+              (if keepGoing
+                (invoke action (list-ref files i))
+                keepGoing))
+            (begin)))
         (extern (pathIsSymbolicLinkRaw (path : Path)) : Bool
           (kotlin-call Files isSymbolicLink))
         (extern (pathParent (path : Path)) : Path
@@ -12279,14 +12289,16 @@
        "        } else {"
        "            emptyList()"
        "        }"
-       "        fileLoop@ for (file in files) {"
+       "        forEachFileUntil(files) { file ->"
        "            val truth = try {"
        "                jsonObjectFromText(readLocalText(file))"
        "            } catch (_: Exception) {"
-       "                continue"
+       "                null"
+       "            }"
+       "            if (truthPresent(truth)) {"
+       "                appendLearnedExamplesFromTruth(examples, MAX_LEARNED_EXAMPLES, file.name, truthJsonObjectOrEmpty(truth))"
        "            }"
-       "            appendLearnedExamplesFromTruth(examples, MAX_LEARNED_EXAMPLES, file.name, truth)"
-       "            if (learnedExamplesFull(learnedExamplesCount(examples), MAX_LEARNED_EXAMPLES)) break@fileLoop"
+       "            !learnedExamplesFull(learnedExamplesCount(examples), MAX_LEARNED_EXAMPLES)"
        "        }"
        "        val learned = learnedExamplesDocument(examples, MAX_LEARNED_EXAMPLES)"
        "        atomicWriteText(containedLeaf(learnedDir, learnedExamplesFileName()), learned.toString(2))"