diff options
Diffstat (limited to 'tools/bootstrap_lectionary.ml')
| -rw-r--r-- | tools/bootstrap_lectionary.ml | 159 |
1 files changed, 150 insertions, 9 deletions
diff --git a/tools/bootstrap_lectionary.ml b/tools/bootstrap_lectionary.ml index 52c7e50..a4c82ae 100644 --- a/tools/bootstrap_lectionary.ml +++ b/tools/bootstrap_lectionary.ml @@ -52,12 +52,67 @@ let parse_ini path = close_in ic; List.rev !sections +(* Task 8 (branch ef-lectionary, differential fix round): lectio's own ini + section names are NOT always the slug {!Rite_ef.Temporal_ef} computes + for the IDENTICAL office. Confirmed the hard way: the first version of + this generator carried section names through {!Slug.of_string} + verbatim, so the data these renamed families need was sitting in this + very file all along -- under lectio's spelling -- while + [Lectionary_ef.readings]' step 2 looked it up under colitur's own, + found nothing, and silently fell through to step 3's ferial-resumption + answer instead. Invisible until test/test_differential.ml first + compared citation CONTENT (this task): a day's SLUG/rank/colour already + matched, so nothing before this task ever noticed the READING was + wrong. [colitur_keys] is the closed translation table -- the SAME + families test/test_differential.ml's own Layer A ([norm_slug]) already + established as pure vocabulary, carrying no liturgical substance, not + re-derived here. Kept in the generator, not in [Lectionary_ef.readings] + itself, because a bootstrap step exists exactly to translate an + external vocabulary into colitur's own ONCE, at data-generation time -- + baking an alias table into the rite's own runtime lookup would just + move the vocabulary problem, not solve it. + + A translation can widen ONE ini section into several colitur keys + (Passiontide: lectio never distinguishes Passion week from Holy week at + the slug level, "ef-passiontide-0-<weekday>" for both -- confirmed + empirically, its OWN computed reading is byte-identical between the two + weeks' same weekday throughout 2005-2050 -- so both of colitur's own + week-specific keys legitimately point at the one source entry); it + never narrows or drops one, and every key not named here passes through + unchanged (e.g. "ef-easter-8-{monday,tuesday,thursday}", the three + non-Ember Pentecost-octave ferias colitur does NOT rename). *) +let weekdays = [ "monday"; "tuesday"; "wednesday"; "thursday"; "friday"; "saturday" ] + +let colitur_keys name = + if String.equal name "ef-christmas-sunday-0" then + (* WIDEN, not rename -- fix round (found by test_lectionary_ef.ml's own + pre-existing test_step3_christmas_feria_resumes_sunday going from + PASS to FAIL): "ef-christmas-sunday-0" is not only lectio's own + calendar-level slug for RG 17(a)'s Holy Name Sunday + (test_differential.ml's own [norm_slug] comment) -- it is ALSO + colitur's own GENUINE, DIRECTLY-COMPUTED temporal slug (Rite_ef. + Temporal_ef.temporal, "if m = 12 && dd >= 26 then Some + \"ef-christmas-sunday-0\"") for an ordinary Sunday landing on 26-28 + December, the historical "Sunday within the Octave of the Nativity" + -- a DIFFERENT civil window than Holy Name Sunday (2-5 January), and + Missal-confirmed (docs/research/scan1.txt, "Dominica infra octavam + Nativitatis Domini, II classis") to be the IDENTICAL Mass (Gal. + 4,1-7 / Luc. 2,33-40), not a coincidence. The first version of this + translation REPLACED the key outright and broke that pre-existing, + working case -- caught by the existing test suite, not by this + generator's own reasoning; keeping the original key alongside the + Holy-Name-Sunday alias fixes it, following the same "widen, never + narrow" rule Passiontide below already established. *) + [ "ef-christmas-sunday-0"; "ef-holy-name-sunday" ] + else if String.equal name "ef-easter-8-wednesday" then [ "ef-pentecost-ember-wed" ] + else if String.equal name "ef-easter-8-friday" then [ "ef-pentecost-ember-fri" ] + else if String.equal name "ef-easter-8-saturday" then [ "ef-pentecost-ember-sat" ] + else ( + match List.find_opt (fun wd -> String.equal name ("ef-passiontide-0-" ^ wd)) weekdays with + | Some wd -> [ "ef-passiontide-1-" ^ wd; "ef-passiontide-2-" ^ wd ] + | None -> [ name ]) + let convert sec = - let slug = - match Slug.of_string sec.name with - | Ok s -> s - | Error e -> die "bad slug %S: %s" sec.name e - in let cite part key = match List.assoc_opt key sec.fields with | None | Some "" -> None @@ -69,7 +124,86 @@ let convert sec = die "%s: has one reading, not two -- an Epistle without a Gospel (or the \ reverse) is malformed and must be investigated, not silently shipped" sec.name; - (slug, cs) + List.map + (fun key -> + match Slug.of_string key with + | Ok slug -> (slug, cs) + | Error e -> die "bad slug %S (translated from %S): %s" key sec.name e) + (colitur_keys sec.name) + +(* [ef-nativity-vigil] (RG 91 entry 5, {!Rite_ef.Temporal_ef}'s own [named]) + is a TEMPORAL office with no section of its own in THIS ini at all -- + lectio computes ITS citations from a different source file entirely, + its SANCTORAL calendar (tridentine-calendar.ini's own + "[vigil-of-christmas]" section: "reading.first = Rom 1:1-6", + "reading.gospel = Matt 1:18-21"). colitur's own sanctoral bootstrap + (Task 3) already carried those identical citations onto + data/ef/sanctoral.sexp's own `vigil-of-christmas` entry -- inert there + because data/ef/adjustments.sexp suppresses it (that overlay's own + comment: the SAME celebration as this temporal office, not a second + one) -- which corroborates this value independently rather than merely + asserting it. Hand-authored here, the same discipline + data/ef/adjustments.sexp's own RG 110 companion and Major Litanies + `Add` directives already use for a genuine upstream-source gap this + generator's own single-ini design cannot reach on its own. *) +let vigil_entries = + [ ( (match Slug.of_string "ef-nativity-vigil" with Ok s -> s | Error e -> die "%s" e), + [ { Citation.part = Citation.First; reference = "Rom 1:1-6" }; + { Citation.part = Citation.Gospel; reference = "Matt 1:18-21" } ] ) + ] + +(* One more colitur-only slug, DERIVED from [ef-holy-name-sunday]'s own + citations (just translated above) rather than a second hand-typed copy + of the same text: [ef-holy-name] is RG 17(a)'s own fallback ("secus die + 2 ianuarii", 2 January in a year with no Sunday 2-5 January). The + calendarium's own table (data/ef/expected-divergences.sexp's own C16 + note quotes it) gives ONE heading for both the Sunday and the fallback + shape -- the identical Mass, not two -- so this is the same citation + pair, not an independent lookup. Safe to hard-wire (unlike a step-3 + fallback, which would walk back into a DIFFERENT, unrelated Sunday of + the OLD liturgical year): RG 17(a)'s whole point is that this Mass is + said in place of, not alongside, whatever ferial reading a bare + fallback would otherwise find. + + REJECTED, and recorded so it is not re-attempted: giving + [ef-nativity-octave-day-{5,6,7}] (29-31 December, RG 91 entry 17) this + SAME derived value too. Tried, then measured against the real + differential and REVERTED -- it is wrong. lectio's own citation for + those three dates is NOT uniform across years (confirmed against the + fixture: 2005-12-29 reads "Heb 1:1-12"/"John 1:1-14", 2006-12-29 reads + "1 Cor. 4:1-5"/"Luke 3:1-6" -- two different Masses, not one). Read + against the Missal directly (docs/research/scan1.txt, "Dominica infra + octavam Nativitatis Domini, II classis": Epistle "Gal. 4, 1-7", Gospel + "Luc. 2, 33-40" -- the SAME pair as Holy Name Sunday, corroborating the + guess would have been right ONLY for that specific case): the two + observed fixture values are each the PREVIOUS true civil Sunday's OWN + Mass -- Christmas Day itself (25 Dec 2005 was a Sunday that year: + "In Nativitate Domini... Missa in die", Heb 1:1-12/John 1:1-14) or, in + a year with no Sunday between Christmas and New Year at all, all the + way back to Advent IV (24 Dec 2006 was a Sunday; 1 Cor. 4:1-5/Luke + 3:1-6 is that Mass's own citation, already in [ef-advent-sunday-4] + above). colitur's OWN existing step 3 ([Lectionary_ef.readings], NOT + this generator) already walks back to the true PRECEDING CIVIL Sunday + regardless of season and would find EXACTLY these same answers on its + own -- a hard-wired entry here would have SHORT-CIRCUITED that correct, + already-general mechanism with one wrong, uniform guess. Left absent + deliberately: these three dates stay whatever step 3 resolves through + [ef-advent-sunday-4]/[ef-holy-name-sunday] et al, or [] on a date whose + own preceding Sunday has no entry either (data/ef/expected- + divergences.sexp's own C21 entry records what remains, if anything, + after that). *) +let derived_entries entries = + let holy_name_sunday_citations = + match + List.find_opt (fun (s, _) -> String.equal (Slug.to_string s) "ef-holy-name-sunday") entries + with + | Some (_, cs) -> cs + | None -> + die "internal: ef-holy-name-sunday missing after translation -- cannot derive its dependants" + in + match Slug.of_string "ef-holy-name" with + | Ok s -> [ (s, holy_name_sunday_citations) ] + | Error e -> die "%s" e let sha256 path = let ic = Unix.open_process_in (Printf.sprintf "sha256sum %s" (Filename.quote path)) in @@ -81,7 +215,8 @@ let () = let src = if Array.length Sys.argv > 1 then Sys.argv.(1) else default_source in let dst = if Array.length Sys.argv > 2 then Sys.argv.(2) else default_dest in let secs = parse_ini src in - let entries = List.map convert secs in + let translated = List.concat_map convert secs in + let entries = translated @ vigil_entries @ derived_entries translated in let lect = match Lectionary.of_entries entries with | Ok l -> l @@ -96,9 +231,15 @@ let () = ;\n\ ; Source: %s\n\ ; SHA-256: %s\n\ - ; %d entries. Regenerate with:\n\ + ; %d entries (%d ini sections translated/widened into colitur's own\n\ + ; Temporal_ef vocabulary via [colitur_keys]; %d hand-authored from a\n\ + ; second source file [vigil_entries]; %d derived from an already-\n\ + ; translated entry above rather than re-typed [derived_entries] --\n\ + ; see this generator's own comments on all three). Regenerate with:\n\ ; eval $(opam env) && dune exec tools/bootstrap_lectionary.exe -- %s %s\n" - src (sha256 src) (List.length entries) src dst; + src (sha256 src) (List.length entries) (List.length secs) (List.length vigil_entries) + (List.length entries - List.length translated - List.length vigil_entries) + src dst; Sexplib.Sexp.output_hum oc (Lectionary.sexp_of_t lect); output_char oc '\n'; close_out oc; |
