ponomar-ts 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/LICENSE +674 -0
  2. package/NOTICE.md +27 -0
  3. package/README.md +105 -0
  4. package/dist/core/calendar/jdate.d.ts +52 -0
  5. package/dist/core/calendar/jdate.d.ts.map +1 -0
  6. package/dist/core/calendar/jdate.js +151 -0
  7. package/dist/core/calendar/jdate.js.map +1 -0
  8. package/dist/core/calendar/pcalendar.d.ts +21 -0
  9. package/dist/core/calendar/pcalendar.d.ts.map +1 -0
  10. package/dist/core/calendar/pcalendar.js +33 -0
  11. package/dist/core/calendar/pcalendar.js.map +1 -0
  12. package/dist/core/dsl/eval.d.ts +10 -0
  13. package/dist/core/dsl/eval.d.ts.map +1 -0
  14. package/dist/core/dsl/eval.js +83 -0
  15. package/dist/core/dsl/eval.js.map +1 -0
  16. package/dist/core/dsl/index.d.ts +4 -0
  17. package/dist/core/dsl/index.d.ts.map +1 -0
  18. package/dist/core/dsl/index.js +4 -0
  19. package/dist/core/dsl/index.js.map +1 -0
  20. package/dist/core/dsl/lexer.d.ts +14 -0
  21. package/dist/core/dsl/lexer.d.ts.map +1 -0
  22. package/dist/core/dsl/lexer.js +121 -0
  23. package/dist/core/dsl/lexer.js.map +1 -0
  24. package/dist/core/dsl/parser.d.ts +25 -0
  25. package/dist/core/dsl/parser.d.ts.map +1 -0
  26. package/dist/core/dsl/parser.js +103 -0
  27. package/dist/core/dsl/parser.js.map +1 -0
  28. package/dist/data/divineLiturgy.d.ts +3 -0
  29. package/dist/data/divineLiturgy.d.ts.map +1 -0
  30. package/dist/data/divineLiturgy.js +80 -0
  31. package/dist/data/divineLiturgy.js.map +1 -0
  32. package/dist/data/index.d.ts +6 -0
  33. package/dist/data/index.d.ts.map +1 -0
  34. package/dist/data/index.js +8 -0
  35. package/dist/data/index.js.map +1 -0
  36. package/dist/data/menaion.d.ts +3 -0
  37. package/dist/data/menaion.d.ts.map +1 -0
  38. package/dist/data/menaion.js +18363 -0
  39. package/dist/data/menaion.js.map +1 -0
  40. package/dist/data/pentecostarion.d.ts +3 -0
  41. package/dist/data/pentecostarion.d.ts.map +1 -0
  42. package/dist/data/pentecostarion.js +4096 -0
  43. package/dist/data/pentecostarion.js.map +1 -0
  44. package/dist/data/triodion.d.ts +3 -0
  45. package/dist/data/triodion.d.ts.map +1 -0
  46. package/dist/data/triodion.js +841 -0
  47. package/dist/data/triodion.js.map +1 -0
  48. package/dist/data/types.d.ts +30 -0
  49. package/dist/data/types.d.ts.map +1 -0
  50. package/dist/data/types.js +5 -0
  51. package/dist/data/types.js.map +1 -0
  52. package/dist/engine/day.d.ts +23 -0
  53. package/dist/engine/day.d.ts.map +1 -0
  54. package/dist/engine/day.js +41 -0
  55. package/dist/engine/day.js.map +1 -0
  56. package/dist/engine/index.d.ts +20 -0
  57. package/dist/engine/index.d.ts.map +1 -0
  58. package/dist/engine/index.js +26 -0
  59. package/dist/engine/index.js.map +1 -0
  60. package/dist/engine/lookup.d.ts +7 -0
  61. package/dist/engine/lookup.d.ts.map +1 -0
  62. package/dist/engine/lookup.js +30 -0
  63. package/dist/engine/lookup.js.map +1 -0
  64. package/dist/engine/resolve.d.ts +15 -0
  65. package/dist/engine/resolve.d.ts.map +1 -0
  66. package/dist/engine/resolve.js +30 -0
  67. package/dist/engine/resolve.js.map +1 -0
  68. package/dist/index.d.ts +17 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +16 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/paschalion.d.ts +31 -0
  73. package/dist/paschalion.d.ts.map +1 -0
  74. package/dist/paschalion.js +60 -0
  75. package/dist/paschalion.js.map +1 -0
  76. package/package.json +89 -0
  77. package/src/core/calendar/jdate.ts +192 -0
  78. package/src/core/calendar/pcalendar.ts +47 -0
  79. package/src/core/dsl/eval.ts +94 -0
  80. package/src/core/dsl/index.ts +15 -0
  81. package/src/core/dsl/lexer.ts +121 -0
  82. package/src/core/dsl/parser.ts +148 -0
  83. package/src/data/divineLiturgy.ts +82 -0
  84. package/src/data/index.ts +8 -0
  85. package/src/data/menaion.ts +18365 -0
  86. package/src/data/pentecostarion.ts +4098 -0
  87. package/src/data/triodion.ts +843 -0
  88. package/src/data/types.ts +35 -0
  89. package/src/engine/day.ts +67 -0
  90. package/src/engine/index.ts +44 -0
  91. package/src/engine/lookup.ts +34 -0
  92. package/src/engine/resolve.ts +49 -0
  93. package/src/index.ts +17 -0
  94. package/src/paschalion.ts +80 -0
package/NOTICE.md ADDED
@@ -0,0 +1,27 @@
1
+ # Notice
2
+
3
+ **ponomar-ts** is a derivative work of the [Ponomar Java project](https://github.com/typiconman/ponomar).
4
+
5
+ ## Upstream
6
+
7
+ - **Project:** Ponomar
8
+ - **Website:** https://www.ponomar.net/
9
+ - **Source:** https://github.com/typiconman/ponomar
10
+ - **License:** GNU General Public License v3.0 or later
11
+ - **Copyright:** 2006-2018 Aleksandr Andreev and others
12
+
13
+ The upstream project's `README.md` states:
14
+
15
+ > Ponomar is free software: you can redistribute it and/or modify it under the
16
+ > terms of the GNU General Public License as published by the Free Software
17
+ > Foundation, either version 3 of the License, or (at your option) any later version.
18
+
19
+ ## This port
20
+
21
+ Where source files in this repository were translated from the corresponding
22
+ Java source in the Ponomar project, the file header will name the upstream
23
+ counterpart. Translations of the XML data corpus (menaion, triodion,
24
+ pentekostarion, oktoechos, saints biographies) retain upstream copyright and
25
+ license.
26
+
27
+ If you spot missing attribution, please open an issue.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # ponomar-ts
2
+
3
+ A TypeScript port of the [Ponomar](https://github.com/typiconman/ponomar) Orthodox liturgics engine.
4
+
5
+ > [!WARNING]
6
+ > **Status: pre-alpha.** Nothing works yet. This repository contains scaffolding
7
+ > and the beginnings of a paschal-date module. Do not depend on it for anything.
8
+
9
+ ## What this is
10
+
11
+ The original [Ponomar](https://www.ponomar.net/) is a Java + XML rule engine
12
+ maintained by Aleksandr Andreev and contributors since 2006. It computes
13
+ liturgical information (saints, readings, tone, fasting, feast transfer rules)
14
+ by following the Orthodox Typicon precisely, driven by declarative XML data
15
+ files that encode each day's rubrics.
16
+
17
+ **ponomar-ts** aims to be a faithful port of the *engine and the data* to
18
+ TypeScript, so it can be consumed by modern JS/TS applications (Node servers,
19
+ Next.js apps, mobile React Native builds) without a JVM or a desktop UI.
20
+
21
+ ### Scope
22
+
23
+ Ported:
24
+
25
+ - [ ] Paschalion (Meeus' luni-solar algorithm; Julian → Gregorian conversion)
26
+ - [ ] Day / Days aggregate
27
+ - [ ] Commemoration selection & feast-rank transfers
28
+ - [ ] Gospel / Epistle pericope resolution (including Lukan Jump and reserves)
29
+ - [ ] Oktoechos tone rotation
30
+ - [ ] Fasting rule classification
31
+ - [ ] XML data loader for the Ponomar `languages/` corpus
32
+
33
+ Not in scope (left to the original Java project):
34
+
35
+ - Swing desktop UI
36
+ - Font rendering and Church Slavonic typography
37
+ - Full service assembly (Matins, Hours, Divine Liturgy)
38
+ - Icon display
39
+ - Liturgical music library
40
+
41
+ ## Installation
42
+
43
+ Not yet published. Once released:
44
+
45
+ ```bash
46
+ npm install ponomar-ts
47
+ ```
48
+
49
+ ## Development
50
+
51
+ The upstream Ponomar Java repo is vendored as a git submodule under
52
+ `vendor/ponomar/`, and its XML rule data is precompiled to typed TypeScript
53
+ at build time by `scripts/codegen/`. The compiled library ships no XML and
54
+ has no XML parser at runtime.
55
+
56
+ ```powershell
57
+ git clone https://github.com/Wolftrail/ponomar-ts.git
58
+ cd ponomar-ts
59
+ git submodule update --init --recursive
60
+ npm install
61
+ npm run codegen # regenerate src/data/ from vendor/ (once codegen lands)
62
+ npm run typecheck
63
+ npm test
64
+ ```
65
+
66
+ See [PLAN.md](PLAN.md) for the port roadmap and phase breakdown.
67
+
68
+ ## Usage
69
+
70
+ ```ts
71
+ // Preview API — subject to change.
72
+ import { getOrthodoxPascha } from "ponomar-ts/paschalion";
73
+
74
+ const pascha = getOrthodoxPascha(2026);
75
+ // -> { year: 2026, month: 4, day: 19 }
76
+ ```
77
+
78
+ ## Design goals
79
+
80
+ - **Zero runtime dependencies.** Pure TypeScript, works in Node ≥ 20.
81
+ - **Tree-shakable ESM.** Deep imports (`ponomar-ts/paschalion`) return small,
82
+ focused modules; the top-level export is the sum of them.
83
+ - **No I/O in the core.** Data files are loaded through pluggable providers so
84
+ the same core can run in Node (filesystem), the browser (fetch), or from a
85
+ precomputed SQLite bake.
86
+ - **Faithful to the Java engine.** Where behavior is ambiguous, we defer to
87
+ the original Java implementation and reference the source file in comments.
88
+ - **Testable against Ponomar Perl API.** The upstream project also ships a
89
+ Perl API; its regression outputs are the ground truth for our own tests.
90
+
91
+ ## License
92
+
93
+ **GPL-3.0-or-later** — matching the upstream Ponomar Java project. This is a
94
+ derivative work.
95
+
96
+ The XML data files reproduced from Ponomar (menaion, triodion, pentekostarion,
97
+ oktoechos) retain their upstream license and copyright. See `LICENSE` for the
98
+ full GPL-3.0 text and `NOTICE.md` (once added) for attribution details.
99
+
100
+ ## Related projects
101
+
102
+ - [typiconman/ponomar](https://github.com/typiconman/ponomar) — the original Java engine and XML corpus
103
+ - [brianglass/orthocal-python](https://github.com/brianglass/orthocal-python) — Django-based Orthodox calendar (Slavic)
104
+ - [OliverBrotchie/orthodox-calendar](https://github.com/OliverBrotchie/orthodox-calendar) — GOARCH ICS → Unix `calendar(1)` data files (Greek)
105
+ - [holytrinityorthodox.com](https://www.holytrinityorthodox.com/calendar/) — HTC's public Slavic calendar (Jordanville)
@@ -0,0 +1,52 @@
1
+ import type { CalendarDate } from "./pcalendar.ts";
2
+ /** A calendar date on the Julian calendar plus its Julian Day Number. */
3
+ export interface JulianDate {
4
+ readonly year: number;
5
+ readonly month: number;
6
+ readonly day: number;
7
+ readonly jdn: number;
8
+ }
9
+ /** Julian calendar leap year rule: every year divisible by 4. */
10
+ export declare function isJulianLeapYear(year: number): boolean;
11
+ /** Maximum day number for a (Julian-calendar) month/year combination. */
12
+ export declare function daysInMonth(year: number, month: number): number;
13
+ /**
14
+ * Build a `JulianDate` from Julian-calendar year/month/day. Throws
15
+ * `RangeError` if any field is out of range for the calendar.
16
+ */
17
+ export declare function julianDate(year: number, month: number, day: number): JulianDate;
18
+ /** Build a `JulianDate` from its Julian Day Number. */
19
+ export declare function julianDateFromJdn(jdn: number): JulianDate;
20
+ /** Add `n` days (may be negative); returns a new `JulianDate`. */
21
+ export declare function addDays(date: JulianDate, n: number): JulianDate;
22
+ /** Subtract `n` days (may be negative); returns a new `JulianDate`. */
23
+ export declare function subtractDays(date: JulianDate, n: number): JulianDate;
24
+ /**
25
+ * Signed difference in days between two dates: `a.jdn - b.jdn`. Matches
26
+ * upstream `JDate.difference(former, latter)`.
27
+ */
28
+ export declare function difference(a: JulianDate, b: JulianDate): number;
29
+ /** Day of week where Sunday = 0, Monday = 1, ... Saturday = 6. */
30
+ export declare function dayOfWeek(date: JulianDate): 0 | 1 | 2 | 3 | 4 | 5 | 6;
31
+ /**
32
+ * Zero-indexed day of year on the Julian calendar (Jan 1 == 0). Matches
33
+ * upstream `JDate.getDoy()`.
34
+ */
35
+ export declare function dayOfYear(date: JulianDate): number;
36
+ export declare function equals(a: JulianDate, b: JulianDate): boolean;
37
+ export declare function compare(a: JulianDate, b: JulianDate): number;
38
+ /**
39
+ * Convert a Julian-calendar date to the proleptic Gregorian calendar via
40
+ * Julian Day Number.
41
+ */
42
+ export declare function toGregorian(date: JulianDate): CalendarDate;
43
+ /** Convert a proleptic Gregorian date to a Julian-calendar `JulianDate`. */
44
+ export declare function fromGregorian(date: CalendarDate): JulianDate;
45
+ declare function gregorianYmdToJdn(year: number, month: number, day: number): number;
46
+ declare function jdnToGregorianYmd(jdn: number): CalendarDate;
47
+ export declare const _internal: {
48
+ readonly gregorianYmdToJdn: typeof gregorianYmdToJdn;
49
+ readonly jdnToGregorianYmd: typeof jdnToGregorianYmd;
50
+ };
51
+ export {};
52
+ //# sourceMappingURL=jdate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jdate.d.ts","sourceRoot":"","sources":["../../../src/core/calendar/jdate.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,yEAAyE;AACzE,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAQD,iEAAiE;AACjE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAM/D;AAgBD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAG/E;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAMzD;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAK/D;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAEpE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAE/D;AAED,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAGrE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAGlD;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAE5D;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CAE1D;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,CAE5D;AA6BD,iBAAS,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAa3E;AAED,iBAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAWpD;AAKD,eAAO,MAAM,SAAS;;;CAGZ,CAAC"}
@@ -0,0 +1,151 @@
1
+ // Ported from Ponomar/JDate.java (typiconman/ponomar).
2
+ // The upstream Java class is a mutable Julian-calendar date backed by a
3
+ // Julian Day Number (JDN). This TS port is an immutable value object with the
4
+ // same JDN as the source of truth, plus pre-computed Y/M/D fields.
5
+ //
6
+ // Notes on differences vs upstream:
7
+ // * All operations return new values (no mutation).
8
+ // * `dayOfYear` matches upstream's zero-indexed convention (Jan 1 == 0).
9
+ // * `difference(a, b) = a.jdn - b.jdn` matches upstream's static method
10
+ // `JDate.difference(former, latter)`.
11
+ const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
12
+ const DAYS_IN_MONTH_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
13
+ const MONTH_DOY = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
14
+ const MONTH_DOY_LEAP = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335];
15
+ /** Julian calendar leap year rule: every year divisible by 4. */
16
+ export function isJulianLeapYear(year) {
17
+ return year % 4 === 0;
18
+ }
19
+ /** Maximum day number for a (Julian-calendar) month/year combination. */
20
+ export function daysInMonth(year, month) {
21
+ if (!Number.isInteger(month) || month < 1 || month > 12) {
22
+ throw new RangeError(`month must be 1..12, got ${month}`);
23
+ }
24
+ const table = isJulianLeapYear(year) ? DAYS_IN_MONTH_LEAP : DAYS_IN_MONTH;
25
+ return table[month - 1];
26
+ }
27
+ function assertValid(year, month, day) {
28
+ if (!Number.isInteger(year) || year < 1) {
29
+ throw new RangeError(`year must be a positive integer, got ${year}`);
30
+ }
31
+ if (!Number.isInteger(month) || month < 1 || month > 12) {
32
+ throw new RangeError(`month must be 1..12, got ${month}`);
33
+ }
34
+ if (!Number.isInteger(day) || day < 1 || day > daysInMonth(year, month)) {
35
+ throw new RangeError(`day must be 1..${daysInMonth(year, month)} for ${year}-${month}, got ${day}`);
36
+ }
37
+ }
38
+ /**
39
+ * Build a `JulianDate` from Julian-calendar year/month/day. Throws
40
+ * `RangeError` if any field is out of range for the calendar.
41
+ */
42
+ export function julianDate(year, month, day) {
43
+ assertValid(year, month, day);
44
+ return { year, month, day, jdn: julianYmdToJdn(year, month, day) };
45
+ }
46
+ /** Build a `JulianDate` from its Julian Day Number. */
47
+ export function julianDateFromJdn(jdn) {
48
+ if (!Number.isInteger(jdn) || jdn < 0) {
49
+ throw new RangeError(`jdn must be a non-negative integer, got ${jdn}`);
50
+ }
51
+ const { year, month, day } = jdnToJulianYmd(jdn);
52
+ return { year, month, day, jdn };
53
+ }
54
+ /** Add `n` days (may be negative); returns a new `JulianDate`. */
55
+ export function addDays(date, n) {
56
+ if (!Number.isInteger(n)) {
57
+ throw new RangeError(`n must be an integer, got ${n}`);
58
+ }
59
+ return julianDateFromJdn(date.jdn + n);
60
+ }
61
+ /** Subtract `n` days (may be negative); returns a new `JulianDate`. */
62
+ export function subtractDays(date, n) {
63
+ return addDays(date, -n);
64
+ }
65
+ /**
66
+ * Signed difference in days between two dates: `a.jdn - b.jdn`. Matches
67
+ * upstream `JDate.difference(former, latter)`.
68
+ */
69
+ export function difference(a, b) {
70
+ return a.jdn - b.jdn;
71
+ }
72
+ /** Day of week where Sunday = 0, Monday = 1, ... Saturday = 6. */
73
+ export function dayOfWeek(date) {
74
+ // JDN 0 was a Monday; (jdn + 1) mod 7 yields Sunday-first index.
75
+ return ((date.jdn + 1) % 7);
76
+ }
77
+ /**
78
+ * Zero-indexed day of year on the Julian calendar (Jan 1 == 0). Matches
79
+ * upstream `JDate.getDoy()`.
80
+ */
81
+ export function dayOfYear(date) {
82
+ const table = isJulianLeapYear(date.year) ? MONTH_DOY_LEAP : MONTH_DOY;
83
+ return table[date.month - 1] + date.day - 1;
84
+ }
85
+ export function equals(a, b) {
86
+ return a.jdn === b.jdn;
87
+ }
88
+ export function compare(a, b) {
89
+ return a.jdn - b.jdn;
90
+ }
91
+ /**
92
+ * Convert a Julian-calendar date to the proleptic Gregorian calendar via
93
+ * Julian Day Number.
94
+ */
95
+ export function toGregorian(date) {
96
+ return jdnToGregorianYmd(date.jdn);
97
+ }
98
+ /** Convert a proleptic Gregorian date to a Julian-calendar `JulianDate`. */
99
+ export function fromGregorian(date) {
100
+ return julianDateFromJdn(gregorianYmdToJdn(date.year, date.month, date.day));
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // Low-level JDN conversions (Meeus / Fliegel-van Flandern style, integer only)
104
+ function julianYmdToJdn(year, month, day) {
105
+ const a = Math.floor((14 - month) / 12);
106
+ const y = year + 4800 - a;
107
+ const m = month + 12 * a - 3;
108
+ return (day + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4) - 32083);
109
+ }
110
+ function jdnToJulianYmd(jdn) {
111
+ const c = jdn + 32082;
112
+ const d = Math.floor((4 * c + 3) / 1461);
113
+ const e = c - Math.floor((1461 * d) / 4);
114
+ const m = Math.floor((5 * e + 2) / 153);
115
+ const day = e - Math.floor((153 * m + 2) / 5) + 1;
116
+ const month = m + 3 - 12 * Math.floor(m / 10);
117
+ const year = d - 4800 + Math.floor(m / 10);
118
+ return { year, month, day };
119
+ }
120
+ function gregorianYmdToJdn(year, month, day) {
121
+ const a = Math.floor((14 - month) / 12);
122
+ const y = year + 4800 - a;
123
+ const m = month + 12 * a - 3;
124
+ return (day +
125
+ Math.floor((153 * m + 2) / 5) +
126
+ 365 * y +
127
+ Math.floor(y / 4) -
128
+ Math.floor(y / 100) +
129
+ Math.floor(y / 400) -
130
+ 32045);
131
+ }
132
+ function jdnToGregorianYmd(jdn) {
133
+ const a = jdn + 32044;
134
+ const b = Math.floor((4 * a + 3) / 146097);
135
+ const c = a - Math.floor((146097 * b) / 4);
136
+ const d = Math.floor((4 * c + 3) / 1461);
137
+ const e = c - Math.floor((1461 * d) / 4);
138
+ const m = Math.floor((5 * e + 2) / 153);
139
+ const day = e - Math.floor((153 * m + 2) / 5) + 1;
140
+ const month = m + 3 - 12 * Math.floor(m / 10);
141
+ const year = 100 * b + d - 4800 + Math.floor(m / 10);
142
+ return { year, month, day };
143
+ }
144
+ // Internal accessors reused by pcalendar.ts to avoid duplicating conversion
145
+ // logic. Kept `internal` in name to signal they are not part of the stable
146
+ // public API.
147
+ export const _internal = {
148
+ gregorianYmdToJdn,
149
+ jdnToGregorianYmd,
150
+ };
151
+ //# sourceMappingURL=jdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jdate.js","sourceRoot":"","sources":["../../../src/core/calendar/jdate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /** A proleptic Gregorian calendar date (all fields 1-based). */
2
+ export interface CalendarDate {
3
+ readonly year: number;
4
+ readonly month: number;
5
+ readonly day: number;
6
+ }
7
+ /**
8
+ * Gregorian calendar offset (in days) that must be *added* to a Julian date
9
+ * to obtain the same civil day on the Gregorian calendar, for the given AD
10
+ * year. Every non-leap Gregorian century adds one day. Correct from 1583
11
+ * (Gregorian reform) forward.
12
+ */
13
+ export declare function julianToGregorianOffset(year: number): number;
14
+ /**
15
+ * Add `n` days to a Gregorian calendar date. Handles month/year boundaries.
16
+ * `n` may be negative.
17
+ */
18
+ export declare function addDays(date: CalendarDate, n: number): CalendarDate;
19
+ /** Signed difference in days between two Gregorian dates (`a - b`). */
20
+ export declare function difference(a: CalendarDate, b: CalendarDate): number;
21
+ //# sourceMappingURL=pcalendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pcalendar.d.ts","sourceRoot":"","sources":["../../../src/core/calendar/pcalendar.ts"],"names":[],"mappings":"AAMA,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO5D;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,GAAG,YAAY,CAMnE;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAKnE"}
@@ -0,0 +1,33 @@
1
+ // Proleptic Gregorian calendar utilities. The Gregorian date shape and its
2
+ // small helper set live here so that `paschalion.ts` and `core/calendar/jdate.ts`
3
+ // can share one definition of `CalendarDate` and one JDN-based conversion path.
4
+ import { _internal } from "./jdate.js";
5
+ /**
6
+ * Gregorian calendar offset (in days) that must be *added* to a Julian date
7
+ * to obtain the same civil day on the Gregorian calendar, for the given AD
8
+ * year. Every non-leap Gregorian century adds one day. Correct from 1583
9
+ * (Gregorian reform) forward.
10
+ */
11
+ export function julianToGregorianOffset(year) {
12
+ if (!Number.isInteger(year) || year < 1583) {
13
+ throw new RangeError(`Gregorian conversion is only defined from 1583 onward, got ${year}`);
14
+ }
15
+ return Math.floor(year / 100) - Math.floor(year / 400) - 2;
16
+ }
17
+ /**
18
+ * Add `n` days to a Gregorian calendar date. Handles month/year boundaries.
19
+ * `n` may be negative.
20
+ */
21
+ export function addDays(date, n) {
22
+ if (!Number.isInteger(n)) {
23
+ throw new RangeError(`n must be an integer, got ${n}`);
24
+ }
25
+ const jdn = _internal.gregorianYmdToJdn(date.year, date.month, date.day);
26
+ return _internal.jdnToGregorianYmd(jdn + n);
27
+ }
28
+ /** Signed difference in days between two Gregorian dates (`a - b`). */
29
+ export function difference(a, b) {
30
+ return (_internal.gregorianYmdToJdn(a.year, a.month, a.day) -
31
+ _internal.gregorianYmdToJdn(b.year, b.month, b.day));
32
+ }
33
+ //# sourceMappingURL=pcalendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pcalendar.js","sourceRoot":"","sources":["../../../src/core/calendar/pcalendar.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,kFAAkF;AAClF,gFAAgF;AAEhF,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AASvC;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IACnD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,UAAU,CACnB,8DAA8D,IAAI,EAAE,CACpE,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,IAAkB,EAAE,CAAS;IACpD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,GAAG,GAAG,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACzE,OAAO,SAAS,CAAC,iBAAiB,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,UAAU,CAAC,CAAe,EAAE,CAAe;IAC1D,OAAO,CACN,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC;QACnD,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CACnD,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type Expr, ParseError } from "./parser.ts";
2
+ export type Context = Readonly<Record<string, number | boolean>>;
3
+ export declare class EvalError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ export declare function evaluate(source: string, ctx: Context): number;
7
+ export declare function evaluateBool(source: string, ctx: Context): boolean;
8
+ export declare function evaluateAst(expr: Expr, ctx: Context): number;
9
+ export { ParseError };
10
+ //# sourceMappingURL=eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../../src/core/dsl/eval.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,IAAI,EAAE,UAAU,EAAS,MAAM,aAAa,CAAC;AAE3D,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;AAEjE,qBAAa,SAAU,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI3B;AAOD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAE7D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAElE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAE5D;AA0DD,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,83 @@
1
+ // Ported from Ponomar/StringOp.java (typiconman/ponomar) — evaluator.
2
+ //
3
+ // Semantics mirror upstream:
4
+ // * Every operator returns a `double`. Booleans are 1.0 / 0.0.
5
+ // * `&&`, `||`, `!` coerce their operands via `value !== 0 → true`.
6
+ // * `true` / `false` are reserved identifiers.
7
+ // * Variables come from a plain lookup table. Missing names throw.
8
+ // * Numeric semantics use JS number (IEEE-754 double), matching Java double.
9
+ import { ParseError, parse } from "./parser.js";
10
+ export class EvalError extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = "EvalError";
14
+ }
15
+ }
16
+ const RESERVED = {
17
+ true: 1,
18
+ false: 0,
19
+ };
20
+ export function evaluate(source, ctx) {
21
+ return evalExpr(parse(source), ctx);
22
+ }
23
+ export function evaluateBool(source, ctx) {
24
+ return evalExpr(parse(source), ctx) !== 0;
25
+ }
26
+ export function evaluateAst(expr, ctx) {
27
+ return evalExpr(expr, ctx);
28
+ }
29
+ function evalExpr(expr, ctx) {
30
+ switch (expr.kind) {
31
+ case "number":
32
+ return expr.value;
33
+ case "ident": {
34
+ const reserved = RESERVED[expr.name];
35
+ if (reserved !== undefined)
36
+ return reserved;
37
+ if (!Object.prototype.hasOwnProperty.call(ctx, expr.name)) {
38
+ throw new EvalError(`Unknown variable ${JSON.stringify(expr.name)}`);
39
+ }
40
+ const v = ctx[expr.name];
41
+ if (typeof v === "boolean")
42
+ return v ? 1 : 0;
43
+ if (typeof v !== "number" || !Number.isFinite(v)) {
44
+ throw new EvalError(`Variable ${JSON.stringify(expr.name)} is not a finite number`);
45
+ }
46
+ return v;
47
+ }
48
+ case "unary": {
49
+ const v = evalExpr(expr.operand, ctx);
50
+ return expr.op === "!" ? (v !== 0 ? 0 : 1) : -v;
51
+ }
52
+ case "binary": {
53
+ // Short-circuit && / ||: safe here because expressions are pure.
54
+ if (expr.op === "&&") {
55
+ return evalExpr(expr.left, ctx) !== 0 && evalExpr(expr.right, ctx) !== 0
56
+ ? 1
57
+ : 0;
58
+ }
59
+ if (expr.op === "||") {
60
+ return evalExpr(expr.left, ctx) !== 0 || evalExpr(expr.right, ctx) !== 0
61
+ ? 1
62
+ : 0;
63
+ }
64
+ const l = evalExpr(expr.left, ctx);
65
+ const r = evalExpr(expr.right, ctx);
66
+ switch (expr.op) {
67
+ case "==": return l === r ? 1 : 0;
68
+ case "!=": return l !== r ? 1 : 0;
69
+ case "<": return l < r ? 1 : 0;
70
+ case "<=": return l <= r ? 1 : 0;
71
+ case ">": return l > r ? 1 : 0;
72
+ case ">=": return l >= r ? 1 : 0;
73
+ case "+": return l + r;
74
+ case "-": return l - r;
75
+ case "*": return l * r;
76
+ case "/": return l / r;
77
+ case "%": return l % r;
78
+ }
79
+ }
80
+ }
81
+ }
82
+ export { ParseError };
83
+ //# sourceMappingURL=eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.js","sourceRoot":"","sources":["../../../src/core/dsl/eval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { EvalError, evaluate, evaluateAst, evaluateBool, type Context, } from "./eval.ts";
2
+ export { LexError, tokenize, type Token, type TokenKind } from "./lexer.ts";
3
+ export { ParseError, parse, type BinaryOp, type Expr, type UnaryOp, } from "./parser.ts";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/dsl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,KAAK,OAAO,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EACN,UAAU,EACV,KAAK,EACL,KAAK,QAAQ,EACb,KAAK,IAAI,EACT,KAAK,OAAO,GACZ,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { EvalError, evaluate, evaluateAst, evaluateBool, } from "./eval.js";
2
+ export { LexError, tokenize } from "./lexer.js";
3
+ export { ParseError, parse, } from "./parser.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/dsl/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GAEZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAA8B,MAAM,YAAY,CAAC;AAC5E,OAAO,EACN,UAAU,EACV,KAAK,GAIL,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type TokenKind = "NUMBER" | "IDENT" | "LP" | "RP" | "PLUS" | "MINUS" | "STAR" | "SLASH" | "PERCENT" | "EQ" | "NE" | "LT" | "LE" | "GT" | "GE" | "AND" | "OR" | "NOT" | "EOF";
2
+ export interface Token {
3
+ readonly kind: TokenKind;
4
+ readonly text: string;
5
+ /** 0-based source offset where this token starts. */
6
+ readonly pos: number;
7
+ }
8
+ export declare class LexError extends Error {
9
+ readonly source: string;
10
+ readonly pos: number;
11
+ constructor(message: string, source: string, pos: number);
12
+ }
13
+ export declare function tokenize(source: string): Token[];
14
+ //# sourceMappingURL=lexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../src/core/dsl/lexer.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,SAAS,GAClB,QAAQ,GACR,OAAO,GACP,IAAI,GACJ,IAAI,GACJ,MAAM,GACN,OAAO,GACP,MAAM,GACN,OAAO,GACP,SAAS,GACT,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,KAAK,GACL,KAAK,CAAC;AAET,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,QAAS,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBACT,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAMxD;AAYD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,CAmDhD"}