From 67715584937a81fd957db77884dec8e572b2e6cd Mon Sep 17 00:00:00 2001 From: Vikram Bhaskaran Date: Thu, 16 Jan 2025 18:36:02 +1100 Subject: [PATCH 1/2] Removed lazy_static * Latest iteration of Rust can perform LazyLock which is what lazy_static was used for --- Cargo.lock | 5 ---- Cargo.toml | 1 - bindings-python/Cargo.lock | 2 -- vidyut-chandas/Cargo.toml | 1 - vidyut-chandas/src/sounds.rs | 10 +++----- vidyut-cheda/Cargo.toml | 1 - vidyut-cheda/src/normalize_text.rs | 9 +++---- vidyut-cheda/src/sounds.rs | 22 ++++++---------- vidyut-prakriya/ARCHITECTURE.md | 21 ---------------- vidyut-prakriya/Cargo.lock | 1 - vidyut-prakriya/Cargo.toml | 3 +-- vidyut-prakriya/src/angasya/abhyasasya.rs | 7 +++--- vidyut-prakriya/src/krt/basic.rs | 6 ++--- vidyut-prakriya/src/sounds.rs | 7 ++---- vidyut-prakriya/src/tripadi/pada_8_2.rs | 11 ++++---- vidyut-prakriya/src/tripadi/pada_8_4.rs | 11 ++++---- .../tests/integration/kashika_1_1.rs | 7 +++--- .../tests/integration/kashika_3_1.rs | 7 +++--- .../tests/integration/kashika_6_1.rs | 7 +++--- .../tests/integration/kashika_6_2.rs | 7 +++--- vidyut-sandhi/Cargo.toml | 1 - vidyut-sandhi/src/generator.rs | 11 +++----- vidyut-sandhi/src/sounds.rs | 16 +++++------- vidyut-sandhi/src/splitter.rs | 25 +++++++++---------- 24 files changed, 68 insertions(+), 131 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8076ea..f901185 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1789,7 +1789,6 @@ version = "0.1.0" dependencies = [ "csv", "glob", - "lazy_static", "multimap", "vidyut-chandas", "vidyut-cheda", @@ -1805,7 +1804,6 @@ name = "vidyut-chandas" version = "0.1.0" dependencies = [ "console_error_panic_hook", - "lazy_static", "serde", "serde-wasm-bindgen", "serde_derive", @@ -1819,7 +1817,6 @@ dependencies = [ "clap", "compact_str 0.8.1", "env_logger", - "lazy_static", "log", "priority-queue", "regex", @@ -1891,7 +1888,6 @@ dependencies = [ "csv", "enumset", "flate2", - "lazy_static", "rayon", "rmp-serde", "rustc-hash", @@ -1924,7 +1920,6 @@ dependencies = [ "clap", "compact_str 0.7.1", "csv", - "lazy_static", "rustc-hash", "tempfile", ] diff --git a/Cargo.toml b/Cargo.toml index 52ae845..eb5c817 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,6 @@ vidyut-prakriya = { path = "./vidyut-prakriya" } vidyut-sandhi = { path = "./vidyut-sandhi" } csv = "1.1.6" multimap = "0.8.3" -lazy_static = "1.4.0" glob = "0.3.1" [workspace.dependencies] diff --git a/bindings-python/Cargo.lock b/bindings-python/Cargo.lock index 559bfe4..d9d24f7 100644 --- a/bindings-python/Cargo.lock +++ b/bindings-python/Cargo.lock @@ -727,7 +727,6 @@ name = "vidyut-chandas" version = "0.1.0" dependencies = [ "console_error_panic_hook", - "lazy_static", "serde", "serde-wasm-bindgen", "serde_derive", @@ -811,7 +810,6 @@ dependencies = [ "clap", "compact_str 0.7.1", "csv", - "lazy_static", "rustc-hash", ] diff --git a/vidyut-chandas/Cargo.toml b/vidyut-chandas/Cargo.toml index 0c8c4bd..100a528 100644 --- a/vidyut-chandas/Cargo.toml +++ b/vidyut-chandas/Cargo.toml @@ -12,7 +12,6 @@ edition = "2021" [dependencies] console_error_panic_hook = "0.1.7" -lazy_static = "1.4.0" serde = { version = "1.0.150", features = ["derive"] } serde-wasm-bindgen = "0.4" serde_derive = "1.0.193" diff --git a/vidyut-chandas/src/sounds.rs b/vidyut-chandas/src/sounds.rs index 8927be4..fb129db 100644 --- a/vidyut-chandas/src/sounds.rs +++ b/vidyut-chandas/src/sounds.rs @@ -1,10 +1,8 @@ -use lazy_static::lazy_static; +use std::sync::LazyLock; -lazy_static! { - static ref HRASVA: Set = Set::from("aiufx"); - static ref AC: Set = Set::from("aAiIuUfFxXeEoO"); - static ref HAL: Set = Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL"); -} +static HRASVA: LazyLock = LazyLock::new(|| Set::from("aiufx")); +static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); +static HAL: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL")); type Sound = char; diff --git a/vidyut-cheda/Cargo.toml b/vidyut-cheda/Cargo.toml index 0a10174..bef858e 100644 --- a/vidyut-cheda/Cargo.toml +++ b/vidyut-cheda/Cargo.toml @@ -13,7 +13,6 @@ compact_str = "0.8.1" clap = { workspace = true } log = { workspace = true } env_logger = { workspace = true } -lazy_static = "1.5.0" regex = "1.11.1" rmp-serde = { workspace = true } serde = {workspace = true } diff --git a/vidyut-cheda/src/normalize_text.rs b/vidyut-cheda/src/normalize_text.rs index 06daa54..fa96f15 100644 --- a/vidyut-cheda/src/normalize_text.rs +++ b/vidyut-cheda/src/normalize_text.rs @@ -1,4 +1,5 @@ -use lazy_static::lazy_static; +use std::sync::LazyLock; + use regex::Regex; /// Creates a normalized version of `text` that is easier to process. @@ -8,10 +9,8 @@ use regex::Regex; /// 2. Delete all whitespace spans. /// 3. Separate all remaining spans with a single " ". pub fn normalize(text: &str) -> String { - lazy_static! { - static ref RE: Regex = - Regex::new(r"([a-zA-Z']+)|(\s+)|([^a-zA-Z']+)").expect("always defined"); - } + static RE: LazyLock = + LazyLock::new(|| Regex::new(r"([a-zA-Z']+)|(\s+)|([^a-zA-Z']+)").expect("always defined")); let mut ret = RE .find_iter(text) diff --git a/vidyut-cheda/src/sounds.rs b/vidyut-cheda/src/sounds.rs index 88fe105..524d4ba 100644 --- a/vidyut-cheda/src/sounds.rs +++ b/vidyut-cheda/src/sounds.rs @@ -1,6 +1,6 @@ //! Utility functions for checking Sanskrit sounds. -use lazy_static::lazy_static; +use std::sync::LazyLock; /// A set of Sanskrit sounds. /// @@ -42,10 +42,8 @@ impl Default for SoundSet { /// - other punctuation characters (|, ||, numbers) /// - characters or symbols from non-SLP1 encodings pub fn is_sanskrit(c: char) -> bool { - lazy_static! { - static ref CHARS: SoundSet = - SoundSet::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'"); - } + static CHARS: LazyLock = + LazyLock::new(|| SoundSet::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'")); CHARS.contains(c) } @@ -53,9 +51,7 @@ pub fn is_sanskrit(c: char) -> bool { /// /// `ac` is the Paninian name for the Sanskrit vowels. pub fn is_ac(c: char) -> bool { - lazy_static! { - static ref AC: SoundSet = SoundSet::from("aAiIuUfFxXeEoO"); - } + static AC: LazyLock = LazyLock::new(|| SoundSet::from("aAiIuUfFxXeEoO")); AC.contains(c) } @@ -64,18 +60,16 @@ pub fn is_ac(c: char) -> bool { /// `hal` is the Paninian name for the Sanskrit consonants. #[allow(unused)] pub fn is_hal(c: char) -> bool { - lazy_static! { - static ref HAL: SoundSet = SoundSet::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL"); - } + static HAL: LazyLock = + LazyLock::new(|| SoundSet::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL")); HAL.contains(c) } /// Returns whether the given sound is voiced. #[allow(unused)] pub fn is_ghosha(c: char) -> bool { - lazy_static! { - static ref GHOSHA: SoundSet = SoundSet::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh"); - } + static GHOSHA: LazyLock = + LazyLock::new(|| SoundSet::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); GHOSHA.contains(c) } diff --git a/vidyut-prakriya/ARCHITECTURE.md b/vidyut-prakriya/ARCHITECTURE.md index 4d357b8..b04c3e8 100644 --- a/vidyut-prakriya/ARCHITECTURE.md +++ b/vidyut-prakriya/ARCHITECTURE.md @@ -8,7 +8,6 @@ our system. This document assumes some familiarity with basic Rust concepts like structs, enums, closures, and lifetimes. - Goals and values ---------------- @@ -40,7 +39,6 @@ than wait for perfect clarity. Fortunately, we have found that as the program has grown and matured, we have become more and more able to remove hacks and solve problems in a more fundamental way. - Core data types --------------- @@ -66,21 +64,18 @@ In addition to these three types, we recommend exploring the types in the part of its API. Our hope is that callers can lean on Rust's type system to define meaningful requests and receive correct derivations. - Core modules ------------ We start our description here with the high-level `vyakarana` module then work our way into specific implementation details. - ### `vyakarana` This defines the public API. Given certain input conditions, the method here return all `Prakriya`s compatible with those conditions. `vyakarana` is a thin wrapper over the `ashtadhyayi` module, which we describe below. - ### `args` This defines the argument types that `Vyakarana` accepts. The types here follow @@ -89,8 +84,6 @@ Paninian categories as closely as possible, so we have types like `Dhatu`, arguments are well formed. For example, a `Krdanta` must have a `Dhatu` and a `Krt`. - - ### `ashtadhyayi` This defines the core rules of the Ashtadhayi. Given the input constraints @@ -118,7 +111,6 @@ their own modules. Some examples: - `unadipatha`, which defines the rules of the Unadipatha. These rules enter the Ashtadhyayi through rule 3.3.1 (*uṇādayo bahulam*) - ### `prakriya`, `terms`, and `tags` These define the `Prakriya` and `Term` types, as well as some useful secondary @@ -130,7 +122,6 @@ variety of ad-hoc flags. Since `Term` and `Tag` are not stable, we do not expose them in our public API. - ### `prakriya_stack` This module defines utilities for exploring different paths of optional rules. @@ -138,13 +129,11 @@ The core type here is `PrakriyaStack`, which manages a stack of rule paths. (`RulePathStack` might be a clearer name, but it doesn't quite roll off the tongue!) - ### `sounds` This defines various functions for testing and modifying Sanskrit sounds. The core data structure here is `Set`, which stores sounds in a simple array. - Code style ---------- @@ -165,7 +154,6 @@ the logic of each rule more obvious. Here, `p` is a `Prakriya`, `i` is the index of some `Term` within the `Prakriya`, and `|t| ...` is a closure (inline function) that accepts a `Term`. - ### Closures `run_at`, like many of the methods on `Prakriya`, accepts a closure. @@ -188,7 +176,6 @@ for `p.terms[i]`. `Prakriya` also defines many methods for working with indices, such as `find_first_where`, `find_last_where`, `find_next_where`, and so on. - ### Naming conventions Since we have so many rules to write, we use short variable names for common @@ -203,7 +190,6 @@ concepts. Some examples: [rust-borrow]: https://users.rust-lang.org/t/newbie-mut-with-nested-structs/84755 [rust-q]: https://doc.rust-lang.org/rust-by-example/std/result/question_mark.html - Control flow ------------ @@ -226,7 +212,6 @@ directly encodes a critical principle of the grammar. The sections below extend the example above and illustrate the various kinds of control flow we use, ordered from least to most complex. - ### Rule sequences The control flow in the example above is appropriate for simple sequences of @@ -241,7 +226,6 @@ if condition_2 { } ``` - ### Simple rule blocking A natural extension is to use `if`-`else` chains to enforce that only one rule @@ -257,7 +241,6 @@ if condition_1 { } ``` - ### Falling through If a rule is optional, we might wish to "fall through" and consider other @@ -277,7 +260,6 @@ if condition_2 { Here, `rule_2` is accessible even if we reject `rule_1`. - ### Simple locking If we fall through in a simple way, we could end up running both `rule_1` and @@ -300,7 +282,6 @@ if done { } ``` - ### Extended locking Sometimes, we might wish to implement rule locking over a very large section of @@ -345,7 +326,6 @@ If we use the new `do_something_1` and `do_something_2` methods here, the original `Prakriya` struct, we can access it through `lp.p`. Once the lifetime of `lp` has ended, we can continue using `p` as before. - ### Context-aware locking Suppose we wish to derive a *taddhitānta* that uses a specific @@ -353,4 +333,3 @@ taddhita-pratyaya only if available in a specific meaning context. In this case, we can extend the `LockingPrakriya` pattern above to record other useful metadata, such as the meaning condition we wish to derive (if any). For examples of this pattern, see `KrtPrakriya` and `TaddhitaPrakriya`. - diff --git a/vidyut-prakriya/Cargo.lock b/vidyut-prakriya/Cargo.lock index 6c9e9f0..94bf432 100644 --- a/vidyut-prakriya/Cargo.lock +++ b/vidyut-prakriya/Cargo.lock @@ -542,7 +542,6 @@ dependencies = [ "compact_str", "csv", "enumset", - "lazy_static", "serde", "sha2 0.10.6", "sha256", diff --git a/vidyut-prakriya/Cargo.toml b/vidyut-prakriya/Cargo.toml index 968df6d..caf83b5 100644 --- a/vidyut-prakriya/Cargo.toml +++ b/vidyut-prakriya/Cargo.toml @@ -13,10 +13,9 @@ rust-version = "1.68" [dependencies] enumset = { version = "1.1.3", features = ["serde"] } -lazy_static = "1.4.0" rustc-hash = { workspace = true } serde = { version = "1.0.150", features = ["derive"] } -wasm-bindgen = { version = "0.2", features = ["serde-serialize"]} +wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } serde-wasm-bindgen = "0.4" console_error_panic_hook = "0.1.7" diff --git a/vidyut-prakriya/src/angasya/abhyasasya.rs b/vidyut-prakriya/src/angasya/abhyasasya.rs index 70078f3..664bf31 100644 --- a/vidyut-prakriya/src/angasya/abhyasasya.rs +++ b/vidyut-prakriya/src/angasya/abhyasasya.rs @@ -6,6 +6,8 @@ abhyasasya Runs rules that modify the abhyāsa. */ +use std::sync::LazyLock; + use crate::args::Agama as A; use crate::args::Agama; use crate::args::Aupadeshika; @@ -23,7 +25,6 @@ use crate::dhatu_gana as gana; use crate::it_samjna; use crate::sounds as al; use crate::sounds::{map, s, Map, Set, AC, HAL}; -use lazy_static::lazy_static; const AA: Set = s(&["a"]); const ANUNASIKA: Set = s(&["Yam"]); @@ -33,9 +34,7 @@ const KHAY: Set = s(&["Kay"]); const F_HAL: Set = s(&["f hal"]); const PU_YAN_J: Set = s(&["pu~", "yaR", "j"]); -lazy_static! { - static ref KUH_CU: Map = map("ku~ h", "cu~"); -} +static KUH_CU: LazyLock = LazyLock::new(|| map("ku~ h", "cu~")); /// Simplifies the abhyasa per 7.4.60. fn try_haladi(text: &str) -> TermString { diff --git a/vidyut-prakriya/src/krt/basic.rs b/vidyut-prakriya/src/krt/basic.rs index 7726028..21b0d38 100644 --- a/vidyut-prakriya/src/krt/basic.rs +++ b/vidyut-prakriya/src/krt/basic.rs @@ -70,15 +70,13 @@ use crate::krt::utils::KrtPrakriya; use crate::sounds::{s, Set, AC, HAL, IK}; use crate::stem_gana::TYAD_ADI; use crate::Rule::Varttika; -use lazy_static::lazy_static; +use std::sync::LazyLock; const II: Set = s(&["i"]); const UU: Set = s(&["u"]); const PU: Set = s(&["pu~"]); -lazy_static! { - static ref EMPTY_TERM: Term = Term::make_text(""); -} +static EMPTY_TERM: LazyLock = LazyLock::new(|| Term::make_text("")); /// Tries to add various pratyayas that are just "a." fn try_add_various_pratyayas(kp: &mut KrtPrakriya) { diff --git a/vidyut-prakriya/src/sounds.rs b/vidyut-prakriya/src/sounds.rs index 991b2ae..cbf6318 100644 --- a/vidyut-prakriya/src/sounds.rs +++ b/vidyut-prakriya/src/sounds.rs @@ -34,9 +34,8 @@ We chose SLP1 over something like [WX][wx] merely because we have more familiari [slp1]: https://en.wikipedia.org/wiki/SLP1 [wx]: https://en.wikipedia.org/wiki/WX_notation */ -use lazy_static::lazy_static; use rustc_hash::FxHashMap; -use std::fmt; +use std::{fmt, sync::LazyLock}; type Sound = char; @@ -49,9 +48,7 @@ pub const HAL: Set = s(&["hal"]); pub const YAN: Set = s(&["yaR"]); pub const VAL: Set = s(&["val"]); -lazy_static! { - static ref SOUND_PROPS: FxHashMap = create_sound_props(); -} +static SOUND_PROPS: LazyLock> = LazyLock::new(create_sound_props); /// A set of Sanskrit sounds. /// diff --git a/vidyut-prakriya/src/tripadi/pada_8_2.rs b/vidyut-prakriya/src/tripadi/pada_8_2.rs index ce4e58b..b038442 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_2.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_2.rs @@ -1,3 +1,5 @@ +use std::sync::LazyLock; + use crate::args::Agama as A; use crate::args::Aupadeshika as Au; use crate::args::BaseKrt as K; @@ -16,7 +18,6 @@ use crate::dhatu_gana; use crate::ganapatha; use crate::sounds as al; use crate::sounds::{map, s, Map, Set, AC, HAL, IK, JHAL}; -use lazy_static::lazy_static; const YAN: Set = s(&["yaR"]); const CU: Set = s(&["cu~"]); @@ -25,11 +26,9 @@ const BASH: Set = s(&["baS"]); const JHAL_TO_JASH_EXCEPTIONS: Set = Set::from("cSsh"); const HASH: Set = s(&["haS"]); -lazy_static! { - static ref BASH_TO_BHAZ: Map = map("baS", "Baz"); - static ref JHAL_TO_JASH: Map = map("Jal", "jaS"); - static ref CU_TO_KU: Map = map("cu~", "ku~"); -} +static BASH_TO_BHAZ: LazyLock = LazyLock::new(|| map("baS", "Baz")); +static JHAL_TO_JASH: LazyLock = LazyLock::new(|| map("Jal", "jaS")); +static CU_TO_KU: LazyLock = LazyLock::new(|| map("cu~", "ku~")); fn do_ru_adesha(rule: impl Into, p: &mut Prakriya, i: usize) { p.run_at(rule, i, |t| { diff --git a/vidyut-prakriya/src/tripadi/pada_8_4.rs b/vidyut-prakriya/src/tripadi/pada_8_4.rs index ddb13c5..708f317 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_4.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_4.rs @@ -1,3 +1,5 @@ +use std::sync::LazyLock; + use crate::args::Aupadeshika as Au; use crate::args::Gana; use crate::args::Lakara::*; @@ -10,7 +12,6 @@ use crate::core::Rule::Varttika; use crate::core::{Prakriya, Rule, Tag as T, Term}; use crate::sounds as al; use crate::sounds::{map, s, Map, Set, AC, HAL, JHAL}; -use lazy_static::lazy_static; const AT_KU_PU_M: Set = s(&["aw", "ku~", "pu~", "M"]); const AA: Set = s(&["a"]); @@ -27,11 +28,9 @@ const YAY: Set = s(&["yay"]); const JHAY: Set = s(&["Jay"]); const AT: Set = s(&["aw"]); -lazy_static! { - static ref JHAL_TO_CAR: Map = map("Jal", "car"); - static ref JHAL_TO_JASH: Map = map("Jal", "jaS"); - static ref JHAL_TO_JASH_CAR: Map = map("Jal", "jaS car"); -} +static JHAL_TO_CAR: LazyLock = LazyLock::new(|| map("Jal", "car")); +static JHAL_TO_JASH: LazyLock = LazyLock::new(|| map("Jal", "jaS")); +static JHAL_TO_JASH_CAR: LazyLock = LazyLock::new(|| map("Jal", "jaS car")); /// Runs rules that change `n` to `R`. /// Example: krInAti -> krIRAti. diff --git a/vidyut-prakriya/tests/integration/kashika_1_1.rs b/vidyut-prakriya/tests/integration/kashika_1_1.rs index 4ccdc20..c2a3858 100644 --- a/vidyut-prakriya/tests/integration/kashika_1_1.rs +++ b/vidyut-prakriya/tests/integration/kashika_1_1.rs @@ -1,5 +1,6 @@ extern crate test_utils; -use lazy_static::lazy_static; +use std::sync::LazyLock; + use test_utils::*; use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; @@ -10,9 +11,7 @@ use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha::*; use vidyut_prakriya::args::Unadi; -lazy_static! { - static ref S: Tester = Tester::with_svara_rules(); -} +static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); #[test] fn sutra_1_1_1() { diff --git a/vidyut-prakriya/tests/integration/kashika_3_1.rs b/vidyut-prakriya/tests/integration/kashika_3_1.rs index 48541af..ac8a39a 100644 --- a/vidyut-prakriya/tests/integration/kashika_3_1.rs +++ b/vidyut-prakriya/tests/integration/kashika_3_1.rs @@ -1,5 +1,6 @@ extern crate test_utils; -use lazy_static::lazy_static; +use std::sync::LazyLock; + use test_utils::*; use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; @@ -9,9 +10,7 @@ use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha as TA; use vidyut_prakriya::args::*; -lazy_static! { - static ref S: Tester = Tester::with_svara_rules(); -} +static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); fn sanadi(p: Pratipadika, s: Sanadi) -> Dhatu { Dhatu::nama(p, Some(s)) diff --git a/vidyut-prakriya/tests/integration/kashika_6_1.rs b/vidyut-prakriya/tests/integration/kashika_6_1.rs index c6b6c12..2b83901 100644 --- a/vidyut-prakriya/tests/integration/kashika_6_1.rs +++ b/vidyut-prakriya/tests/integration/kashika_6_1.rs @@ -1,5 +1,6 @@ extern crate test_utils; -use lazy_static::lazy_static; +use std::sync::LazyLock; + use test_utils::*; use vidyut_prakriya::args::BaseKrt as Krt; use vidyut_prakriya::args::Gana::*; @@ -9,9 +10,7 @@ use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha::*; use vidyut_prakriya::args::*; -lazy_static! { - static ref S: Tester = Tester::with_svara_rules(); -} +static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); #[test] fn sutra_6_1_1() { diff --git a/vidyut-prakriya/tests/integration/kashika_6_2.rs b/vidyut-prakriya/tests/integration/kashika_6_2.rs index da5659a..d6b8ad0 100644 --- a/vidyut-prakriya/tests/integration/kashika_6_2.rs +++ b/vidyut-prakriya/tests/integration/kashika_6_2.rs @@ -1,10 +1,9 @@ extern crate test_utils; -use lazy_static::lazy_static; +use std::sync::LazyLock; + use test_utils::*; -lazy_static! { - static ref S: Tester = Tester::with_svara_rules(); -} +static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); #[test] fn sutra_6_2_27() { diff --git a/vidyut-sandhi/Cargo.toml b/vidyut-sandhi/Cargo.toml index 5580984..28d763b 100644 --- a/vidyut-sandhi/Cargo.toml +++ b/vidyut-sandhi/Cargo.toml @@ -9,7 +9,6 @@ edition = "2021" clap = { version = "4.0.12", features = ["derive"] } compact_str = "0.7.1" csv = "1.1.6" -lazy_static = "1.4.0" rustc-hash = "2.1.0" [dev-dependencies] diff --git a/vidyut-sandhi/src/generator.rs b/vidyut-sandhi/src/generator.rs index e88f31e..7c5475f 100644 --- a/vidyut-sandhi/src/generator.rs +++ b/vidyut-sandhi/src/generator.rs @@ -3,8 +3,9 @@ Utilities for generating sandhi rules. For details, see the `create_rules` function below. */ +use std::sync::LazyLock; + use crate::sounds::Set; -use lazy_static::lazy_static; /// All vowels. const AC: &str = "aAiIuUfFxXeEoO"; @@ -63,17 +64,13 @@ fn is_savarna_ac(f: char, s: char) -> bool { /// Returns whether the given sound is voiced. fn is_ghoshavat(c: char) -> bool { - lazy_static! { - static ref S: Set = Set::from(r"aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh"); - } + static S: LazyLock = LazyLock::new(|| Set::from(r"aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); S.contains(c) } /// Returns whether the given sound is nasal. fn is_anunasika(c: char) -> bool { - lazy_static! { - static ref S: Set = Set::from(r"NYRnm"); - } + static S: LazyLock = LazyLock::new(|| Set::from(r"NYRnm")); S.contains(c) } diff --git a/vidyut-sandhi/src/sounds.rs b/vidyut-sandhi/src/sounds.rs index 1a92159..7ef10f9 100644 --- a/vidyut-sandhi/src/sounds.rs +++ b/vidyut-sandhi/src/sounds.rs @@ -1,6 +1,6 @@ //! Utility functions for checking Sanskrit sounds. -use lazy_static::lazy_static; +use std::sync::LazyLock; /// A set of Sanskrit sounds. /// @@ -43,9 +43,8 @@ impl Default for Set { /// - other punctuation characters (|, ||, numbers) /// - characters or symbols from non-SLP1 encodings pub fn is_sanskrit(c: char) -> bool { - lazy_static! { - static ref CHARS: Set = Set::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'"); - } + static CHARS: LazyLock = + LazyLock::new(|| Set::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'")); CHARS.contains(c) } @@ -54,18 +53,15 @@ pub fn is_sanskrit(c: char) -> bool { /// `ac` is the Paninian name for the Sanskrit vowels. #[allow(dead_code)] pub fn is_ac(c: char) -> bool { - lazy_static! { - static ref AC: Set = Set::from("aAiIuUfFxXeEoO"); - } + static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); AC.contains(c) } /// Returns whether the given sound is voiced. #[allow(dead_code)] pub fn is_ghosha(c: char) -> bool { - lazy_static! { - static ref GHOSHA: Set = Set::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh"); - } + static GHOSHA: LazyLock = + LazyLock::new(|| Set::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); GHOSHA.contains(c) } diff --git a/vidyut-sandhi/src/splitter.rs b/vidyut-sandhi/src/splitter.rs index 72a3d7c..b3ea9a9 100644 --- a/vidyut-sandhi/src/splitter.rs +++ b/vidyut-sandhi/src/splitter.rs @@ -17,11 +17,11 @@ use crate::errors::Result; use crate::sounds; use crate::sounds::Set; use compact_str::CompactString; -use lazy_static::lazy_static; use rustc_hash::FxHashMap; use std::cmp; use std::collections::hash_map::Keys; use std::path::Path; +use std::sync::LazyLock; /// Describes the type of sandhi split that occurred. #[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] @@ -331,14 +331,14 @@ fn visarga_to_r(s: &str) -> CompactString { } /// Returns whether the first item in a sandhi split is OK according to some basic heuristics. +#[allow(dead_code)] fn is_good_first(text: &str) -> bool { - lazy_static! { - static ref AC: Set = Set::from("aAiIuUfFxXeEoO"); - static ref SPARSHA: Set = Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm"); - static ref HAL: Set = Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvzSsh"); - // Vowels, standard consonants, and "s" and "r" - static ref VALID_FINALS: Set = Set::from("aAiIuUfFxXeEoOHkNwRtpnmsr"); - } + static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); + static SPARSHA: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm")); + static HAL: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvzSsh")); + // Vowels, standard consonants, and "s" and "r" + static VALID_FINALS: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoOHkNwRtpnmsr")); + let mut chars = text.chars().rev(); if let (Some(y), Some(x)) = (chars.next(), chars.next()) { if (AC.contains(x) && AC.contains(y)) || (HAL.contains(x) && HAL.contains(y)) { @@ -353,11 +353,10 @@ fn is_good_first(text: &str) -> bool { /// Returns whether the second item in a sandhi split is OK according to some basic heuristics. fn is_good_second(text: &str) -> bool { - lazy_static! { - static ref YAN: Set = Set::from("yrlv"); - static ref AC: Set = Set::from("aAiIuUfFxXeEoO"); - static ref SPARSHA: Set = Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm"); - } + static YAN: LazyLock = LazyLock::new(|| Set::from("yrlv")); + static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); + static SPARSHA: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm")); + let mut chars = text.chars(); if let (Some(x), Some(y)) = (chars.next(), chars.next()) { if AC.contains(x) && AC.contains(y) { From d1f8f439b5f4746f78ee54320490bea397dc97ac Mon Sep 17 00:00:00 2001 From: Vikram Bhaskaran Date: Sun, 19 Jan 2025 08:23:24 +1100 Subject: [PATCH 2/2] Changed LazyLock to OnceLock * Made the switch for MSRV compatibility --- vidyut-chandas/src/sounds.rs | 17 +- vidyut-cheda/src/normalize_text.rs | 10 +- vidyut-cheda/src/sounds.rs | 28 +-- vidyut-prakriya/ARCHITECTURE.md | 21 +++ vidyut-prakriya/src/angasya/abhyasasya.rs | 9 +- vidyut-prakriya/src/krt/basic.rs | 6 +- vidyut-prakriya/src/sounds.rs | 9 +- vidyut-prakriya/src/tripadi/pada_8_2.rs | 16 +- vidyut-prakriya/src/tripadi/pada_8_4.rs | 21 ++- .../tests/integration/kashika_1_1.rs | 10 +- .../tests/integration/kashika_3_1.rs | 18 +- .../tests/integration/kashika_6_1.rs | 165 ++++++++++-------- .../tests/integration/kashika_6_2.rs | 40 +++-- vidyut-sandhi/src/generator.rs | 12 +- vidyut-sandhi/src/sounds.rs | 19 +- vidyut-sandhi/src/splitter.rs | 43 +++-- 16 files changed, 271 insertions(+), 173 deletions(-) diff --git a/vidyut-chandas/src/sounds.rs b/vidyut-chandas/src/sounds.rs index fb129db..848e66b 100644 --- a/vidyut-chandas/src/sounds.rs +++ b/vidyut-chandas/src/sounds.rs @@ -1,8 +1,8 @@ -use std::sync::LazyLock; +use std::sync::OnceLock; -static HRASVA: LazyLock = LazyLock::new(|| Set::from("aiufx")); -static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); -static HAL: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL")); +static HRASVA: OnceLock = OnceLock::new(); +static AC: OnceLock = OnceLock::new(); +static HAL: OnceLock = OnceLock::new(); type Sound = char; @@ -35,22 +35,23 @@ impl Set { /// Returns whether `c` is a vowel. pub(crate) fn is_ac(c: Sound) -> bool { - AC.contains(c) + AC.get_or_init(|| Set::from("aAiIuUfFxXeEoO")).contains(c) } /// Returns whether `c` is a short vowel. pub(crate) fn is_hrasva(c: Sound) -> bool { - HRASVA.contains(c) + HRASVA.get_or_init(|| Set::from("aiufx")).contains(c) } /// Returns whether `c` is a consonant. pub(crate) fn is_hal(c: Sound) -> bool { - HAL.contains(c) + HAL.get_or_init(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL")) + .contains(c) } /// Returns whether `c` is a Sanskrit sound. pub(crate) fn is_sanskrit(c: Sound) -> bool { - AC.contains(c) || HAL.contains(c) || matches!(c, 'M' | 'H') + is_ac(c) || is_hal(c) || matches!(c, 'M' | 'H') } /// Returns whether `s` starts with a consonant cluster. diff --git a/vidyut-cheda/src/normalize_text.rs b/vidyut-cheda/src/normalize_text.rs index fa96f15..9e0eccf 100644 --- a/vidyut-cheda/src/normalize_text.rs +++ b/vidyut-cheda/src/normalize_text.rs @@ -1,4 +1,4 @@ -use std::sync::LazyLock; +use std::sync::OnceLock; use regex::Regex; @@ -9,10 +9,12 @@ use regex::Regex; /// 2. Delete all whitespace spans. /// 3. Separate all remaining spans with a single " ". pub fn normalize(text: &str) -> String { - static RE: LazyLock = - LazyLock::new(|| Regex::new(r"([a-zA-Z']+)|(\s+)|([^a-zA-Z']+)").expect("always defined")); + static RE: OnceLock = OnceLock::new(); - let mut ret = RE + let re = + RE.get_or_init(|| Regex::new(r"([a-zA-Z']+)|(\s+)|([^a-zA-Z']+)").expect("always defined")); + + let mut ret = re .find_iter(text) .map(|m| m.as_str()) .filter(|s| !s.trim().is_empty()) diff --git a/vidyut-cheda/src/sounds.rs b/vidyut-cheda/src/sounds.rs index 524d4ba..b433141 100644 --- a/vidyut-cheda/src/sounds.rs +++ b/vidyut-cheda/src/sounds.rs @@ -1,6 +1,6 @@ //! Utility functions for checking Sanskrit sounds. -use std::sync::LazyLock; +use std::sync::OnceLock; /// A set of Sanskrit sounds. /// @@ -42,17 +42,19 @@ impl Default for SoundSet { /// - other punctuation characters (|, ||, numbers) /// - characters or symbols from non-SLP1 encodings pub fn is_sanskrit(c: char) -> bool { - static CHARS: LazyLock = - LazyLock::new(|| SoundSet::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'")); - CHARS.contains(c) + static CHARS: OnceLock = OnceLock::new(); + let chars = + CHARS.get_or_init(|| SoundSet::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'")); + chars.contains(c) } /// Returns whether the given sound is a vowel. /// /// `ac` is the Paninian name for the Sanskrit vowels. pub fn is_ac(c: char) -> bool { - static AC: LazyLock = LazyLock::new(|| SoundSet::from("aAiIuUfFxXeEoO")); - AC.contains(c) + static AC: OnceLock = OnceLock::new(); + let ac = AC.get_or_init(|| SoundSet::from("aAiIuUfFxXeEoO")); + ac.contains(c) } /// Returns whether the given sound is a consonant. @@ -60,17 +62,19 @@ pub fn is_ac(c: char) -> bool { /// `hal` is the Paninian name for the Sanskrit consonants. #[allow(unused)] pub fn is_hal(c: char) -> bool { - static HAL: LazyLock = - LazyLock::new(|| SoundSet::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL")); - HAL.contains(c) + static HAL: OnceLock = OnceLock::new(); + + let hal = HAL.get_or_init(|| SoundSet::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL")); + hal.contains(c) } /// Returns whether the given sound is voiced. #[allow(unused)] pub fn is_ghosha(c: char) -> bool { - static GHOSHA: LazyLock = - LazyLock::new(|| SoundSet::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); - GHOSHA.contains(c) + static GHOSHA: OnceLock = OnceLock::new(); + + let ghosha = GHOSHA.get_or_init(|| SoundSet::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); + ghosha.contains(c) } #[cfg(test)] diff --git a/vidyut-prakriya/ARCHITECTURE.md b/vidyut-prakriya/ARCHITECTURE.md index b04c3e8..4d357b8 100644 --- a/vidyut-prakriya/ARCHITECTURE.md +++ b/vidyut-prakriya/ARCHITECTURE.md @@ -8,6 +8,7 @@ our system. This document assumes some familiarity with basic Rust concepts like structs, enums, closures, and lifetimes. + Goals and values ---------------- @@ -39,6 +40,7 @@ than wait for perfect clarity. Fortunately, we have found that as the program has grown and matured, we have become more and more able to remove hacks and solve problems in a more fundamental way. + Core data types --------------- @@ -64,18 +66,21 @@ In addition to these three types, we recommend exploring the types in the part of its API. Our hope is that callers can lean on Rust's type system to define meaningful requests and receive correct derivations. + Core modules ------------ We start our description here with the high-level `vyakarana` module then work our way into specific implementation details. + ### `vyakarana` This defines the public API. Given certain input conditions, the method here return all `Prakriya`s compatible with those conditions. `vyakarana` is a thin wrapper over the `ashtadhyayi` module, which we describe below. + ### `args` This defines the argument types that `Vyakarana` accepts. The types here follow @@ -84,6 +89,8 @@ Paninian categories as closely as possible, so we have types like `Dhatu`, arguments are well formed. For example, a `Krdanta` must have a `Dhatu` and a `Krt`. + + ### `ashtadhyayi` This defines the core rules of the Ashtadhayi. Given the input constraints @@ -111,6 +118,7 @@ their own modules. Some examples: - `unadipatha`, which defines the rules of the Unadipatha. These rules enter the Ashtadhyayi through rule 3.3.1 (*uṇādayo bahulam*) + ### `prakriya`, `terms`, and `tags` These define the `Prakriya` and `Term` types, as well as some useful secondary @@ -122,6 +130,7 @@ variety of ad-hoc flags. Since `Term` and `Tag` are not stable, we do not expose them in our public API. + ### `prakriya_stack` This module defines utilities for exploring different paths of optional rules. @@ -129,11 +138,13 @@ The core type here is `PrakriyaStack`, which manages a stack of rule paths. (`RulePathStack` might be a clearer name, but it doesn't quite roll off the tongue!) + ### `sounds` This defines various functions for testing and modifying Sanskrit sounds. The core data structure here is `Set`, which stores sounds in a simple array. + Code style ---------- @@ -154,6 +165,7 @@ the logic of each rule more obvious. Here, `p` is a `Prakriya`, `i` is the index of some `Term` within the `Prakriya`, and `|t| ...` is a closure (inline function) that accepts a `Term`. + ### Closures `run_at`, like many of the methods on `Prakriya`, accepts a closure. @@ -176,6 +188,7 @@ for `p.terms[i]`. `Prakriya` also defines many methods for working with indices, such as `find_first_where`, `find_last_where`, `find_next_where`, and so on. + ### Naming conventions Since we have so many rules to write, we use short variable names for common @@ -190,6 +203,7 @@ concepts. Some examples: [rust-borrow]: https://users.rust-lang.org/t/newbie-mut-with-nested-structs/84755 [rust-q]: https://doc.rust-lang.org/rust-by-example/std/result/question_mark.html + Control flow ------------ @@ -212,6 +226,7 @@ directly encodes a critical principle of the grammar. The sections below extend the example above and illustrate the various kinds of control flow we use, ordered from least to most complex. + ### Rule sequences The control flow in the example above is appropriate for simple sequences of @@ -226,6 +241,7 @@ if condition_2 { } ``` + ### Simple rule blocking A natural extension is to use `if`-`else` chains to enforce that only one rule @@ -241,6 +257,7 @@ if condition_1 { } ``` + ### Falling through If a rule is optional, we might wish to "fall through" and consider other @@ -260,6 +277,7 @@ if condition_2 { Here, `rule_2` is accessible even if we reject `rule_1`. + ### Simple locking If we fall through in a simple way, we could end up running both `rule_1` and @@ -282,6 +300,7 @@ if done { } ``` + ### Extended locking Sometimes, we might wish to implement rule locking over a very large section of @@ -326,6 +345,7 @@ If we use the new `do_something_1` and `do_something_2` methods here, the original `Prakriya` struct, we can access it through `lp.p`. Once the lifetime of `lp` has ended, we can continue using `p` as before. + ### Context-aware locking Suppose we wish to derive a *taddhitānta* that uses a specific @@ -333,3 +353,4 @@ taddhita-pratyaya only if available in a specific meaning context. In this case, we can extend the `LockingPrakriya` pattern above to record other useful metadata, such as the meaning condition we wish to derive (if any). For examples of this pattern, see `KrtPrakriya` and `TaddhitaPrakriya`. + diff --git a/vidyut-prakriya/src/angasya/abhyasasya.rs b/vidyut-prakriya/src/angasya/abhyasasya.rs index 664bf31..712b87a 100644 --- a/vidyut-prakriya/src/angasya/abhyasasya.rs +++ b/vidyut-prakriya/src/angasya/abhyasasya.rs @@ -6,7 +6,7 @@ abhyasasya Runs rules that modify the abhyāsa. */ -use std::sync::LazyLock; +use std::sync::OnceLock; use crate::args::Agama as A; use crate::args::Agama; @@ -34,7 +34,7 @@ const KHAY: Set = s(&["Kay"]); const F_HAL: Set = s(&["f hal"]); const PU_YAN_J: Set = s(&["pu~", "yaR", "j"]); -static KUH_CU: LazyLock = LazyLock::new(|| map("ku~ h", "cu~")); +static KUH_CU: OnceLock = OnceLock::new(); /// Simplifies the abhyasa per 7.4.60. fn try_haladi(text: &str) -> TermString { @@ -268,7 +268,10 @@ fn try_general_rules(p: &mut Prakriya, i: usize) -> Option<()> { let abhyasa = p.get(i)?; let dhatu = p.get(i_dhatu)?; - if let Some(val) = KUH_CU.get(abhyasa.adi()?) { + if let Some(val) = KUH_CU + .get_or_init(|| map("ku~ h", "cu~")) + .get(abhyasa.adi()?) + { let n = p.get(i_dhatu + 1)?; if dhatu.has_u("ku\\N") && dhatu.has_gana(Gana::Bhvadi) && n.is(S::yaN) { p.step("7.4.63"); diff --git a/vidyut-prakriya/src/krt/basic.rs b/vidyut-prakriya/src/krt/basic.rs index 21b0d38..73dcd3f 100644 --- a/vidyut-prakriya/src/krt/basic.rs +++ b/vidyut-prakriya/src/krt/basic.rs @@ -70,13 +70,13 @@ use crate::krt::utils::KrtPrakriya; use crate::sounds::{s, Set, AC, HAL, IK}; use crate::stem_gana::TYAD_ADI; use crate::Rule::Varttika; -use std::sync::LazyLock; +use std::sync::OnceLock; const II: Set = s(&["i"]); const UU: Set = s(&["u"]); const PU: Set = s(&["pu~"]); -static EMPTY_TERM: LazyLock = LazyLock::new(|| Term::make_text("")); +static EMPTY_TERM: OnceLock = OnceLock::new(); /// Tries to add various pratyayas that are just "a." fn try_add_various_pratyayas(kp: &mut KrtPrakriya) { @@ -561,7 +561,7 @@ fn try_add_upapada_krt(kp: &mut KrtPrakriya) -> Option { let upapada = match kp.p.get_if(0, |t| t.has_tag(T::Pratipadika)) { Some(t) => t, - None => &EMPTY_TERM, + None => &EMPTY_TERM.get_or_init(|| Term::make_text("")), }; let upapade = kp.p.has(0, |t| t.has_tag(T::Pratipadika)); diff --git a/vidyut-prakriya/src/sounds.rs b/vidyut-prakriya/src/sounds.rs index cbf6318..0d8b099 100644 --- a/vidyut-prakriya/src/sounds.rs +++ b/vidyut-prakriya/src/sounds.rs @@ -35,7 +35,7 @@ We chose SLP1 over something like [WX][wx] merely because we have more familiari [wx]: https://en.wikipedia.org/wiki/WX_notation */ use rustc_hash::FxHashMap; -use std::{fmt, sync::LazyLock}; +use std::{fmt, sync::OnceLock}; type Sound = char; @@ -48,7 +48,7 @@ pub const HAL: Set = s(&["hal"]); pub const YAN: Set = s(&["yaR"]); pub const VAL: Set = s(&["val"]); -static SOUND_PROPS: LazyLock> = LazyLock::new(create_sound_props); +static SOUND_PROPS: OnceLock> = OnceLock::new(); /// A set of Sanskrit sounds. /// @@ -633,17 +633,18 @@ pub const fn savarna(c: Sound) -> Set { pub(crate) fn map(keys: &str, values: &str) -> Map { let keys = s_old(keys); let values = s_old(values); + let sound_props = SOUND_PROPS.get_or_init(|| create_sound_props()); let mut map = Map::new(); for key in keys.to_string().chars() { - let key_props = SOUND_PROPS.get(&key).expect("called statically"); + let key_props = sound_props.get(&key).expect("called statically"); // The best sound has the minimal distance. let best_value = values .to_string() .chars() .min_by_key(|v| { - SOUND_PROPS + sound_props .get(v) .expect("called statically") .distance(key_props) diff --git a/vidyut-prakriya/src/tripadi/pada_8_2.rs b/vidyut-prakriya/src/tripadi/pada_8_2.rs index b038442..2a561da 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_2.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_2.rs @@ -1,4 +1,4 @@ -use std::sync::LazyLock; +use std::sync::OnceLock; use crate::args::Agama as A; use crate::args::Aupadeshika as Au; @@ -26,9 +26,9 @@ const BASH: Set = s(&["baS"]); const JHAL_TO_JASH_EXCEPTIONS: Set = Set::from("cSsh"); const HASH: Set = s(&["haS"]); -static BASH_TO_BHAZ: LazyLock = LazyLock::new(|| map("baS", "Baz")); -static JHAL_TO_JASH: LazyLock = LazyLock::new(|| map("Jal", "jaS")); -static CU_TO_KU: LazyLock = LazyLock::new(|| map("cu~", "ku~")); +static BASH_TO_BHAZ: OnceLock = OnceLock::new(); +static JHAL_TO_JASH: OnceLock = OnceLock::new(); +static CU_TO_KU: OnceLock = OnceLock::new(); fn do_ru_adesha(rule: impl Into, p: &mut Prakriya, i: usize) { p.run_at(rule, i, |t| { @@ -455,7 +455,7 @@ fn per_term_1a(p: &mut Prakriya) -> Option<()> { if x.has_antya(CU) && (is_jhali || is_ante) { if let Some(c) = x.antya() { - let sub = CU_TO_KU.get(c)?; + let sub = CU_TO_KU.get_or_init(|| map("cu~", "ku~")).get(c)?; p.run_at("8.2.30", i, |t| { // TODO: what is the rule that allows this change? if t.has_upadha('Y') { @@ -490,7 +490,9 @@ fn per_term_1b(p: &mut Prakriya) -> Option<()> { }; if x.has_adi(BASH) && x.has_antya(JHAZ) && x.is_ekac() && x.is_dhatu() && if_y { - let sub = BASH_TO_BHAZ.get(x.adi()?)?; + let sub = BASH_TO_BHAZ + .get_or_init(|| map("baS", "Baz")) + .get(x.adi()?)?; p.run_at("8.2.37", i, |t| t.set_adi_char(sub)); } } @@ -515,7 +517,7 @@ fn per_term_1b(p: &mut Prakriya) -> Option<()> { && !t.has_tag_in(&[T::FlagAntyaAcSandhi, T::FlagPratipadikaTiLopa]) { let key = t.antya()?; - let sub = JHAL_TO_JASH.get(key)?; + let sub = JHAL_TO_JASH.get_or_init(|| map("Jal", "jaS")).get(key)?; p.run_at("8.2.39", i, |t| t.set_antya_char(sub)); } } diff --git a/vidyut-prakriya/src/tripadi/pada_8_4.rs b/vidyut-prakriya/src/tripadi/pada_8_4.rs index 708f317..23329aa 100644 --- a/vidyut-prakriya/src/tripadi/pada_8_4.rs +++ b/vidyut-prakriya/src/tripadi/pada_8_4.rs @@ -1,4 +1,4 @@ -use std::sync::LazyLock; +use std::sync::OnceLock; use crate::args::Aupadeshika as Au; use crate::args::Gana; @@ -28,9 +28,9 @@ const YAY: Set = s(&["yay"]); const JHAY: Set = s(&["Jay"]); const AT: Set = s(&["aw"]); -static JHAL_TO_CAR: LazyLock = LazyLock::new(|| map("Jal", "car")); -static JHAL_TO_JASH: LazyLock = LazyLock::new(|| map("Jal", "jaS")); -static JHAL_TO_JASH_CAR: LazyLock = LazyLock::new(|| map("Jal", "jaS car")); +static JHAL_TO_CAR: OnceLock = OnceLock::new(); +static JHAL_TO_JASH: OnceLock = OnceLock::new(); +static JHAL_TO_JASH_CAR: OnceLock = OnceLock::new(); /// Runs rules that change `n` to `R`. /// Example: krInAti -> krIRAti. @@ -377,7 +377,7 @@ fn try_jhal_adesha(ip: &mut IndexPrakriya) -> Option<()> { let x = ip.char_at(&i_x); let y = ip.char_at(i_y); - let sub = JHAL_TO_JASH.get(x); + let sub = JHAL_TO_JASH.get_or_init(|| map("Jal", "jaS")).get(x); if sub.is_some() && JHASH.contains(y) { let sub = sub.expect("present"); if x != sub { @@ -392,7 +392,10 @@ fn try_jhal_adesha(ip: &mut IndexPrakriya) -> Option<()> { // Check for jaz-car to avoid applying a rule that causes no changee. if x.is_abhyasa() && x.has_adi(JHAL) && !x.has_adi(JASH_CAR) { - let sub = JHAL_TO_JASH_CAR.get(x.adi().expect("ok")).expect("ok"); + let sub = JHAL_TO_JASH_CAR + .get_or_init(|| map("Jal", "jaS car")) + .get(x.adi().expect("ok")) + .expect("ok"); ip.p.run_at("8.4.54", i, |t| t.set_adi_char(sub)); } @@ -424,8 +427,9 @@ fn try_jhal_adesha(ip: &mut IndexPrakriya) -> Option<()> { let i_x = ip.prev(i_y)?; let x = ip.char_at(&i_x); let y = ip.char_at(i_y); + let sub = JHAL_TO_CAR.get_or_init(|| map("Jal", "car")).get(x); - if let Some(sub) = JHAL_TO_CAR.get(x) { + if let Some(sub) = sub { if KHAR.contains(y) { if x != sub { ip.run_for_char("8.4.55", &i_x, &sub.to_string()); @@ -437,7 +441,8 @@ fn try_jhal_adesha(ip: &mut IndexPrakriya) -> Option<()> { ip.iter(|ip, i_x| { let x = ip.char_at(i_x); - let sub = JHAL_TO_CAR.get(x); + let sub = JHAL_TO_CAR.get_or_init(|| map("Jal", "car")).get(x); + if let Some(sub) = sub { let last = ip.p.terms().last()?; if x != sub { diff --git a/vidyut-prakriya/tests/integration/kashika_1_1.rs b/vidyut-prakriya/tests/integration/kashika_1_1.rs index c2a3858..30e13c5 100644 --- a/vidyut-prakriya/tests/integration/kashika_1_1.rs +++ b/vidyut-prakriya/tests/integration/kashika_1_1.rs @@ -1,5 +1,5 @@ extern crate test_utils; -use std::sync::LazyLock; +use std::sync::OnceLock; use test_utils::*; use vidyut_prakriya::args::BaseKrt as Krt; @@ -11,7 +11,7 @@ use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha::*; use vidyut_prakriya::args::Unadi; -static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); +static S: OnceLock = OnceLock::new(); #[test] fn sutra_1_1_1() { @@ -270,8 +270,10 @@ fn sutra_1_1_20() { #[test] fn sutra_1_1_21() { - S.assert_has_krdanta(&[], &d("qukf\\Y", Tanadi), Krt::tavya, &["karta/vya"]); - S.assert_has_taddhita("upagu", T::aR, &["Opagava/"]); + let s = S.get_or_init(|| Tester::with_svara_rules()); + + s.assert_has_krdanta(&[], &d("qukf\\Y", Tanadi), Krt::tavya, &["karta/vya"]); + s.assert_has_taddhita("upagu", T::aR, &["Opagava/"]); assert_has_sup_3d("vfkza", Pum, &["vfkzAByAm"]); } diff --git a/vidyut-prakriya/tests/integration/kashika_3_1.rs b/vidyut-prakriya/tests/integration/kashika_3_1.rs index ac8a39a..02409b6 100644 --- a/vidyut-prakriya/tests/integration/kashika_3_1.rs +++ b/vidyut-prakriya/tests/integration/kashika_3_1.rs @@ -1,5 +1,5 @@ extern crate test_utils; -use std::sync::LazyLock; +use std::sync::OnceLock; use test_utils::*; use vidyut_prakriya::args::BaseKrt as Krt; @@ -10,7 +10,7 @@ use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha as TA; use vidyut_prakriya::args::*; -static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); +static S: OnceLock = OnceLock::new(); fn sanadi(p: Pratipadika, s: Sanadi) -> Dhatu { Dhatu::nama(p, Some(s)) @@ -37,19 +37,21 @@ fn sutra_3_1_2() { #[test] fn sutra_3_1_3() { let kf = d("qukf\\Y", Tanadi); - S.assert_has_krdanta(&[], &kf, Krt::tavyat, &["kartavya^"]); - S.assert_has_artha_taddhita("tittiri", TA::TenaProktam, T::CaR, &["tEttirI/ya"]); + let s = S.get_or_init(|| Tester::with_svara_rules()); + s.assert_has_krdanta(&[], &kf, Krt::tavyat, &["kartavya^"]); + s.assert_has_artha_taddhita("tittiri", TA::TenaProktam, T::CaR, &["tEttirI/ya"]); } #[test] fn sutra_3_1_4() { + let s = S.get_or_init(|| Tester::with_svara_rules()); // sup - S.assert_has_sup_1d("dfzad", Pum, &["dfza/dO"]); - S.assert_has_sup_1p("dfzad", Pum, &["dfza/daH"]); + s.assert_has_sup_1d("dfzad", Pum, &["dfza/dO"]); + s.assert_has_sup_1p("dfzad", Pum, &["dfza/daH"]); // pit - S.assert_has_tip(&[], &d("qupa\\ca~^z", Bhvadi), Lat, &["pa/cati"]); - S.assert_has_tip(&[], &d("paWa~", Bhvadi), Lat, &["pa/Wati"]); + s.assert_has_tip(&[], &d("qupa\\ca~^z", Bhvadi), Lat, &["pa/cati"]); + s.assert_has_tip(&[], &d("paWa~", Bhvadi), Lat, &["pa/Wati"]); } #[test] diff --git a/vidyut-prakriya/tests/integration/kashika_6_1.rs b/vidyut-prakriya/tests/integration/kashika_6_1.rs index 2b83901..773b857 100644 --- a/vidyut-prakriya/tests/integration/kashika_6_1.rs +++ b/vidyut-prakriya/tests/integration/kashika_6_1.rs @@ -1,5 +1,5 @@ extern crate test_utils; -use std::sync::LazyLock; +use std::sync::OnceLock; use test_utils::*; use vidyut_prakriya::args::BaseKrt as Krt; @@ -10,7 +10,11 @@ use vidyut_prakriya::args::Taddhita as T; use vidyut_prakriya::args::TaddhitaArtha::*; use vidyut_prakriya::args::*; -static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); +static S: OnceLock = OnceLock::new(); + +fn get_tester() -> &'static Tester { + S.get_or_init(|| Tester::with_svara_rules()) +} #[test] fn sutra_6_1_1() { @@ -1133,174 +1137,193 @@ fn sutra_6_1_141() { #[test] fn sutra_6_1_159() { - S.assert_has_krdanta(&[], &d("kf\\za~", Bhvadi), Krt::GaY, &["karza/"]); + let s = get_tester(); + s.assert_has_krdanta(&[], &d("kf\\za~", Bhvadi), Krt::GaY, &["karza/"]); } #[ignore] #[test] fn sutra_6_1_162() { - S.assert_has_tip(&[], &d("qupa\\ca~^z", Bhvadi), Lat, &["pa/cati"]); - S.assert_has_tip(&[], &d("paWa~", Bhvadi), Lat, &["pa/Wati"]); - S.assert_has_tip(&[], &d("UrRuY", Adadi), Lat, &["UrRo/ti", "UrRO/ti"]); - S.assert_has_tip(&[], &d("gupU~", Bhvadi), Lat, &["gopAya/ti"]); - S.assert_has_tip(&[], &d("yA\\", Adadi), Lat, &["yA/ti"]); + let s = get_tester(); + s.assert_has_tip(&[], &d("qupa\\ca~^z", Bhvadi), Lat, &["pa/cati"]); + s.assert_has_tip(&[], &d("paWa~", Bhvadi), Lat, &["pa/Wati"]); + s.assert_has_tip(&[], &d("UrRuY", Adadi), Lat, &["UrRo/ti", "UrRO/ti"]); + s.assert_has_tip(&[], &d("gupU~", Bhvadi), Lat, &["gopAya/ti"]); + s.assert_has_tip(&[], &d("yA\\", Adadi), Lat, &["yA/ti"]); } #[test] fn sutra_6_1_163() { - S.assert_has_krdanta(&[], &d("Ba\\njo~", Rudhadi), Krt::Gurac, &["BaNgura/"]); - S.assert_has_krdanta(&[], &d("BAsf~\\", Bhvadi), Krt::Gurac, &["BAsura/"]); - S.assert_has_krdanta(&[], &d("YimidA~", Divadi), Krt::Gurac, &["medura/"]); + let s = get_tester(); + s.assert_has_krdanta(&[], &d("Ba\\njo~", Rudhadi), Krt::Gurac, &["BaNgura/"]); + s.assert_has_krdanta(&[], &d("BAsf~\\", Bhvadi), Krt::Gurac, &["BAsura/"]); + s.assert_has_krdanta(&[], &d("YimidA~", Divadi), Krt::Gurac, &["medura/"]); // TODO: others } #[test] fn sutra_6_1_164() { - S.assert_has_artha_taddhita("kuYja", Gotra, T::cPaY, &["kOYjAyana/"]); + let s = get_tester(); + s.assert_has_artha_taddhita("kuYja", Gotra, T::cPaY, &["kOYjAyana/"]); // TODO: where is this from? // S.assert_has_artha_taddhita("muYja", Gotra, T::cPaY, &["mOYjAyana/"]); } #[test] fn sutra_6_1_165() { - S.assert_has_artha_taddhita("naqa", Gotra, T::Pak, &["nAqAyana/"]); - S.assert_has_artha_taddhita("cara", Gotra, T::Pak, &["cArAyaRa/"]); - S.assert_has_artha_taddhita("akza", TenaDivyatiJayatiJitam, T::Wak, &["Akzika/"]); + let s = get_tester(); + s.assert_has_artha_taddhita("naqa", Gotra, T::Pak, &["nAqAyana/"]); + s.assert_has_artha_taddhita("cara", Gotra, T::Pak, &["cArAyaRa/"]); + s.assert_has_artha_taddhita("akza", TenaDivyatiJayatiJitam, T::Wak, &["Akzika/"]); } #[test] fn sutra_6_1_166() { - S.assert_has_sup_1p("tri", Stri, &["tisra/H"]); + let s = get_tester(); + s.assert_has_sup_1p("tri", Stri, &["tisra/H"]); } #[test] fn sutra_6_1_167() { - S.assert_has_sup_2p("catur", Pum, &["catu/raH"]); + let s = get_tester(); + s.assert_has_sup_2p("catur", Pum, &["catu/raH"]); } #[test] fn sutra_6_1_179() { - S.assert_has_sup_3p("zaz", Pum, &["zaqBi/H"]); - S.assert_has_sup_4p("zaz", Pum, &["zaqBya/H"]); - S.assert_has_sup_6p("paYcan", Pum, &["paYcAnA/m"]); - S.assert_has_sup_6p("zaz", Pum, &["zaRRA/m"]); - S.assert_has_sup_6p("saptan", Pum, &["saptAnA/m"]); + let s = get_tester(); + s.assert_has_sup_3p("zaz", Pum, &["zaqBi/H"]); + s.assert_has_sup_4p("zaz", Pum, &["zaqBya/H"]); + s.assert_has_sup_6p("paYcan", Pum, &["paYcAnA/m"]); + s.assert_has_sup_6p("zaz", Pum, &["zaRRA/m"]); + s.assert_has_sup_6p("saptan", Pum, &["saptAnA/m"]); - S.assert_has_sup_3p("tri", Pum, &["triBi/H"]); - S.assert_has_sup_4p("tri", Pum, &["triBya/H"]); - S.assert_has_sup_6p("tri", Pum, &["trayARA/m"]); + s.assert_has_sup_3p("tri", Pum, &["triBi/H"]); + s.assert_has_sup_4p("tri", Pum, &["triBya/H"]); + s.assert_has_sup_6p("tri", Pum, &["trayARA/m"]); // TODO: caturByaH? - S.assert_has_sup_6p("catur", Pum, &["caturRA/m"]); + s.assert_has_sup_6p("catur", Pum, &["caturRA/m"]); // halAdiH? - S.assert_has_sup_2p("catur", Stri, &["cata/sraH"]); + s.assert_has_sup_2p("catur", Stri, &["cata/sraH"]); } #[test] fn sutra_6_1_180() { - S.assert_has_sup_3p("paYcan", Pum, &["paYca/BiH"]); - S.assert_has_sup_3p("saptan", Pum, &["sapta/BiH"]); - S.assert_has_sup_3p("tri", Stri, &["tisf/BiH"]); - S.assert_has_sup_3p("catur", Pum, &["catu/rBiH"]); + let s = get_tester(); + s.assert_has_sup_3p("paYcan", Pum, &["paYca/BiH"]); + s.assert_has_sup_3p("saptan", Pum, &["sapta/BiH"]); + s.assert_has_sup_3p("tri", Stri, &["tisf/BiH"]); + s.assert_has_sup_3p("catur", Pum, &["catu/rBiH"]); // Jali? - S.assert_has_sup_6p("paYcan", Pum, &["paYcAnA/m"]); - S.assert_has_sup_6p("saptan", Pum, &["saptAnA/m"]); + s.assert_has_sup_6p("paYcan", Pum, &["paYcAnA/m"]); + s.assert_has_sup_6p("saptan", Pum, &["saptAnA/m"]); // upottama? - S.assert_has_sup_3p("zaz", Pum, &["zaqBi/H"]); - S.assert_has_sup_4p("zaz", Pum, &["zaqBya/H"]); + s.assert_has_sup_3p("zaz", Pum, &["zaqBi/H"]); + s.assert_has_sup_4p("zaz", Pum, &["zaqBya/H"]); } #[test] fn sutra_6_1_183() { - S.assert_has_sup_3d("div", Pum, &["dyu/ByAm"]); - S.assert_has_sup_3p("div", Pum, &["dyu/BiH"]); + let s = get_tester(); + s.assert_has_sup_3d("div", Pum, &["dyu/ByAm"]); + s.assert_has_sup_3p("div", Pum, &["dyu/BiH"]); // Jal? - S.assert_has_sup_3s("div", Pum, &["di/vA"]); + s.assert_has_sup_3s("div", Pum, &["di/vA"]); } #[test] fn sutra_6_1_185() { let kr = d("qukf\\Y", Tanadi); let hr = d("hf\\Y", Bhvadi); - S.assert_has_krdanta(&[], &san(&kr), Krt::yat, &["cikIrzya^"]); - S.assert_has_krdanta(&[], &san(&hr), Krt::yat, &["jihIrzya^"]); - S.assert_has_krdanta(&[], &kr, Krt::Ryat, &["kArya^"]); - S.assert_has_krdanta(&[], &hr, Krt::Ryat, &["hArya^"]); + let s = get_tester(); + s.assert_has_krdanta(&[], &san(&kr), Krt::yat, &["cikIrzya^"]); + s.assert_has_krdanta(&[], &san(&hr), Krt::yat, &["jihIrzya^"]); + s.assert_has_krdanta(&[], &kr, Krt::Ryat, &["kArya^"]); + s.assert_has_krdanta(&[], &hr, Krt::Ryat, &["hArya^"]); } #[test] fn sutra_6_1_191() { - S.assert_has_sup_1s("sarva", Pum, &["sa/rvaH"]); - S.assert_has_sup_1d("sarva", Pum, &["sa/rvO"]); - S.assert_has_sup_1p("sarva", Pum, &["sa/rve"]); + let s = get_tester(); + s.assert_has_sup_1s("sarva", Pum, &["sa/rvaH"]); + s.assert_has_sup_1d("sarva", Pum, &["sa/rvO"]); + s.assert_has_sup_1p("sarva", Pum, &["sa/rve"]); } #[test] fn sutra_6_1_193() { let kr = d("qukf\\Y", Tanadi); let hr = d("hf\\Y", Bhvadi); - S.assert_has_krdanta(&[], &san(&kr), Krt::Rvul, &["cikI/rzaka"]); - S.assert_has_krdanta(&[], &san(&hr), Krt::Rvul, &["jihI/rzaka"]); + let s = get_tester(); + s.assert_has_krdanta(&[], &san(&kr), Krt::Rvul, &["cikI/rzaka"]); + s.assert_has_krdanta(&[], &san(&hr), Krt::Rvul, &["jihI/rzaka"]); - S.assert_has_taddhita("BOriki", T::viDal, &["BOriki/viDa"]); - S.assert_has_taddhita("BOliki", T::viDal, &["BOliki/viDa"]); - S.assert_has_taddhita("EzukAri", T::Baktal, &["EzukAri/Bakta"]); + s.assert_has_taddhita("BOriki", T::viDal, &["BOriki/viDa"]); + s.assert_has_taddhita("BOliki", T::viDal, &["BOliki/viDa"]); + s.assert_has_taddhita("EzukAri", T::Baktal, &["EzukAri/Bakta"]); } #[test] fn sutra_6_1_197() { - S.assert_has_taddhita("garga", T::yaY, &["gA/rgya"]); + let s = get_tester(); + s.assert_has_taddhita("garga", T::yaY, &["gA/rgya"]); } #[test] fn sutra_6_1_199() { - S.assert_has_sup_1s("paTin", Pum, &["pa/nTAH"]); - S.assert_has_sup_1d("paTin", Pum, &["pa/nTAnO"]); - S.assert_has_sup_1p("paTin", Pum, &["pa/nTAnaH"]); + let s = get_tester(); + s.assert_has_sup_1s("paTin", Pum, &["pa/nTAH"]); + s.assert_has_sup_1d("paTin", Pum, &["pa/nTAnO"]); + s.assert_has_sup_1p("paTin", Pum, &["pa/nTAnaH"]); - S.assert_has_sup_1s("maTin", Pum, &["ma/nTAH"]); - S.assert_has_sup_1d("maTin", Pum, &["ma/nTAnO"]); - S.assert_has_sup_1p("maTin", Pum, &["ma/nTAnaH"]); + s.assert_has_sup_1s("maTin", Pum, &["ma/nTAH"]); + s.assert_has_sup_1d("maTin", Pum, &["ma/nTAnO"]); + s.assert_has_sup_1p("maTin", Pum, &["ma/nTAnaH"]); // TODO: others } #[test] fn sutra_6_1_211() { - S.assert_has_sup_6s("yuzmad", Pum, &["ta/va"]); - S.assert_has_sup_6s("asmad", Pum, &["ma/ma"]); + let s = get_tester(); + s.assert_has_sup_6s("yuzmad", Pum, &["ta/va"]); + s.assert_has_sup_6s("asmad", Pum, &["ma/ma"]); } #[test] fn sutra_6_1_212() { - S.assert_has_sup_4s("yuzmad", Pum, &["tu/Byam"]); - S.assert_has_sup_4s("asmad", Pum, &["ma/hyam"]); + let s = get_tester(); + s.assert_has_sup_4s("yuzmad", Pum, &["tu/Byam"]); + s.assert_has_sup_4s("asmad", Pum, &["ma/hyam"]); } #[test] fn sutra_6_1_217() { let kr = d("qukf\\Y", Tanadi); let hr = d("hf\\Y", Bhvadi); - S.assert_has_krdanta(&[], &kr, Krt::anIyar, &["karaRI/ya"]); - S.assert_has_krdanta(&[], &hr, Krt::anIyar, &["haraRI/ya"]); + let s = get_tester(); + s.assert_has_krdanta(&[], &kr, Krt::anIyar, &["karaRI/ya"]); + s.assert_has_krdanta(&[], &hr, Krt::anIyar, &["haraRI/ya"]); - S.assert_has_taddhita("pawu", T::jAtIyar, &["pawujAtI/ya"]); - S.assert_has_taddhita("mfdu", T::jAtIyar, &["mfdujAtI/ya"]); + s.assert_has_taddhita("pawu", T::jAtIyar, &["pawujAtI/ya"]); + s.assert_has_taddhita("mfdu", T::jAtIyar, &["mfdujAtI/ya"]); } #[test] fn sutra_6_1_222() { let dadhyac = create_upapada_krdanta("daDyac", "daDi", &[], &d("ancu~", Bhvadi), Krt::kvin); - S.assert_has_sup_2p(&dadhyac, Pum, &["daDI/caH"]); - S.assert_has_sup_3s(&dadhyac, Pum, &["daDI/cA"]); - S.assert_has_sup_4s(&dadhyac, Pum, &["daDI/ce"]); + let s = get_tester(); + s.assert_has_sup_2p(&dadhyac, Pum, &["daDI/caH"]); + s.assert_has_sup_3s(&dadhyac, Pum, &["daDI/cA"]); + s.assert_has_sup_4s(&dadhyac, Pum, &["daDI/ce"]); let madhvac = create_upapada_krdanta("maDvac", "maDu", &[], &d("ancu~", Bhvadi), Krt::kvin); - S.assert_has_sup_2p(&madhvac, Pum, &["maDU/caH"]); - S.assert_has_sup_3s(&madhvac, Pum, &["maDU/cA"]); - S.assert_has_sup_4s(&madhvac, Pum, &["maDU/ce"]); + s.assert_has_sup_2p(&madhvac, Pum, &["maDU/caH"]); + s.assert_has_sup_3s(&madhvac, Pum, &["maDU/cA"]); + s.assert_has_sup_4s(&madhvac, Pum, &["maDU/ce"]); } diff --git a/vidyut-prakriya/tests/integration/kashika_6_2.rs b/vidyut-prakriya/tests/integration/kashika_6_2.rs index d6b8ad0..8c42b91 100644 --- a/vidyut-prakriya/tests/integration/kashika_6_2.rs +++ b/vidyut-prakriya/tests/integration/kashika_6_2.rs @@ -1,47 +1,57 @@ extern crate test_utils; -use std::sync::LazyLock; +use std::sync::OnceLock; use test_utils::*; -static S: LazyLock = LazyLock::new(|| Tester::with_svara_rules()); +static S: OnceLock = OnceLock::new(); + +fn get_tester() -> &'static Tester { + S.get_or_init(|| Tester::with_svara_rules()) +} #[test] fn sutra_6_2_27() { - S.assert_has_karmadharaya("kumAra", "pratyenas", &["ku/mArapratyenas"]); + let s = get_tester(); + s.assert_has_karmadharaya("kumAra", "pratyenas", &["ku/mArapratyenas"]); } #[ignore] #[test] fn sutra_6_2_179() { - S.assert_has_bahuvrihi("antar", "vana", &["antarvaRa/"]); + let s = get_tester(); + s.assert_has_bahuvrihi("antar", "vana", &["antarvaRa/"]); } #[ignore] #[test] fn sutra_6_2_180() { - S.assert_has_bahuvrihi("pra", "antar", &["prAnta/r"]); + let s = get_tester(); + s.assert_has_bahuvrihi("pra", "antar", &["prAnta/r"]); } #[test] fn sutra_6_2_185() { - S.assert_has_bahuvrihi("aBi", "muKa", &["aBimuKa/"]); + let s = get_tester(); + s.assert_has_bahuvrihi("aBi", "muKa", &["aBimuKa/"]); } #[test] fn sutra_6_2_186() { - S.assert_has_bahuvrihi("apa", "muKa", &["apamuKa/"]); + let s = get_tester(); + s.assert_has_bahuvrihi("apa", "muKa", &["apamuKa/"]); } #[test] fn sutra_6_2_187() { - S.assert_has_bahuvrihi("apa", "sPiga", &["apasPiga/"]); - S.assert_has_bahuvrihi("apa", "pUta", &["apapUta/"]); - S.assert_has_bahuvrihi("apa", "vIRA", &["apavIRA/"]); - S.assert_has_bahuvrihi("apa", "aYjas", &["apAYja/s"]); - S.assert_has_bahuvrihi("apa", "aDvan", &["apADva/n"]); - S.assert_has_bahuvrihi("apa", "kukzi", &["apakukzi/"]); - S.assert_has_bahuvrihi("apa", "sIra", &["apasIra/"]); - S.assert_has_bahuvrihi("apa", "nAman", &["apanAma/n"]); + let s = get_tester(); + s.assert_has_bahuvrihi("apa", "sPiga", &["apasPiga/"]); + s.assert_has_bahuvrihi("apa", "pUta", &["apapUta/"]); + s.assert_has_bahuvrihi("apa", "vIRA", &["apavIRA/"]); + s.assert_has_bahuvrihi("apa", "aYjas", &["apAYja/s"]); + s.assert_has_bahuvrihi("apa", "aDvan", &["apADva/n"]); + s.assert_has_bahuvrihi("apa", "kukzi", &["apakukzi/"]); + s.assert_has_bahuvrihi("apa", "sIra", &["apasIra/"]); + s.assert_has_bahuvrihi("apa", "nAman", &["apanAma/n"]); // TODO: apahala, etc. } diff --git a/vidyut-sandhi/src/generator.rs b/vidyut-sandhi/src/generator.rs index 7c5475f..2eecc08 100644 --- a/vidyut-sandhi/src/generator.rs +++ b/vidyut-sandhi/src/generator.rs @@ -3,7 +3,7 @@ Utilities for generating sandhi rules. For details, see the `create_rules` function below. */ -use std::sync::LazyLock; +use std::sync::OnceLock; use crate::sounds::Set; @@ -64,14 +64,16 @@ fn is_savarna_ac(f: char, s: char) -> bool { /// Returns whether the given sound is voiced. fn is_ghoshavat(c: char) -> bool { - static S: LazyLock = LazyLock::new(|| Set::from(r"aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); - S.contains(c) + static S: OnceLock = OnceLock::new(); + S.get_or_init(|| Set::from(r"aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); + S.get().unwrap().contains(c) } /// Returns whether the given sound is nasal. fn is_anunasika(c: char) -> bool { - static S: LazyLock = LazyLock::new(|| Set::from(r"NYRnm")); - S.contains(c) + static S: OnceLock = OnceLock::new(); + S.get_or_init(|| Set::from(r"NYRnm")); + S.get().unwrap().contains(c) } /// Returns the lengthened form of a vowel. diff --git a/vidyut-sandhi/src/sounds.rs b/vidyut-sandhi/src/sounds.rs index 7ef10f9..3ad1bdd 100644 --- a/vidyut-sandhi/src/sounds.rs +++ b/vidyut-sandhi/src/sounds.rs @@ -1,6 +1,6 @@ //! Utility functions for checking Sanskrit sounds. -use std::sync::LazyLock; +use std::sync::OnceLock; /// A set of Sanskrit sounds. /// @@ -43,9 +43,9 @@ impl Default for Set { /// - other punctuation characters (|, ||, numbers) /// - characters or symbols from non-SLP1 encodings pub fn is_sanskrit(c: char) -> bool { - static CHARS: LazyLock = - LazyLock::new(|| Set::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'")); - CHARS.contains(c) + static CHARS: OnceLock = OnceLock::new(); + CHARS.get_or_init(|| Set::from("aAiIuUfFxXeEoOMHkKgGNcCjJYwWqQRtTdDnpPbBmyrlvSzshL'")); + CHARS.get().unwrap().contains(c) } /// Returns whether the given sound is a vowel. @@ -53,16 +53,17 @@ pub fn is_sanskrit(c: char) -> bool { /// `ac` is the Paninian name for the Sanskrit vowels. #[allow(dead_code)] pub fn is_ac(c: char) -> bool { - static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); - AC.contains(c) + static AC: OnceLock = OnceLock::new(); + AC.get_or_init(|| Set::from("aAiIuUfFxXeEoO")); + AC.get().unwrap().contains(c) } /// Returns whether the given sound is voiced. #[allow(dead_code)] pub fn is_ghosha(c: char) -> bool { - static GHOSHA: LazyLock = - LazyLock::new(|| Set::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); - GHOSHA.contains(c) + static GHOSHA: OnceLock = OnceLock::new(); + GHOSHA.get_or_init(|| Set::from("aAiIuUfFxXeEoOgGNjJYqQRdDnbBmyrlvh")); + GHOSHA.get().unwrap().contains(c) } #[cfg(test)] diff --git a/vidyut-sandhi/src/splitter.rs b/vidyut-sandhi/src/splitter.rs index b3ea9a9..d6b260d 100644 --- a/vidyut-sandhi/src/splitter.rs +++ b/vidyut-sandhi/src/splitter.rs @@ -21,7 +21,7 @@ use rustc_hash::FxHashMap; use std::cmp; use std::collections::hash_map::Keys; use std::path::Path; -use std::sync::LazyLock; +use std::sync::OnceLock; /// Describes the type of sandhi split that occurred. #[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] @@ -333,39 +333,58 @@ fn visarga_to_r(s: &str) -> CompactString { /// Returns whether the first item in a sandhi split is OK according to some basic heuristics. #[allow(dead_code)] fn is_good_first(text: &str) -> bool { - static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); - static SPARSHA: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm")); - static HAL: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvzSsh")); + static AC: OnceLock = OnceLock::new(); + AC.get_or_init(|| Set::from("aAiIuUfFxXeEoO")); + let ac = AC.get().unwrap(); + + // static SPARSHA: OnceLock = OnceLock::new(); + // SPARSHA.get_or_init(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm")); + // let sparsha = SPARSHA.get().unwrap(); + + static HAL: OnceLock = OnceLock::new(); + HAL.get_or_init(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBmyrlvzSsh")); + let hal = HAL.get().unwrap(); + // Vowels, standard consonants, and "s" and "r" - static VALID_FINALS: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoOHkNwRtpnmsr")); + static VALID_FINALS: OnceLock = OnceLock::new(); + VALID_FINALS.get_or_init(|| Set::from("aAiIuUfFxXeEoOHkNwRtpnmsr")); + let valid_finals = VALID_FINALS.get().unwrap(); let mut chars = text.chars().rev(); if let (Some(y), Some(x)) = (chars.next(), chars.next()) { - if (AC.contains(x) && AC.contains(y)) || (HAL.contains(x) && HAL.contains(y)) { + if (ac.contains(x) && ac.contains(y)) || (hal.contains(x) && hal.contains(y)) { return false; } } match text.chars().last() { - Some(c) => VALID_FINALS.contains(c), + Some(c) => valid_finals.contains(c), None => true, } } /// Returns whether the second item in a sandhi split is OK according to some basic heuristics. fn is_good_second(text: &str) -> bool { - static YAN: LazyLock = LazyLock::new(|| Set::from("yrlv")); - static AC: LazyLock = LazyLock::new(|| Set::from("aAiIuUfFxXeEoO")); - static SPARSHA: LazyLock = LazyLock::new(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm")); + static YAN: OnceLock = OnceLock::new(); + YAN.get_or_init(|| Set::from("yrlv")); + let yan = YAN.get().unwrap(); + + static AC: OnceLock = OnceLock::new(); + AC.get_or_init(|| Set::from("aAiIuUfFxXeEoO")); + let ac = AC.get().unwrap(); + + static SPARSHA: OnceLock = OnceLock::new(); + SPARSHA.get_or_init(|| Set::from("kKgGNcCjJYwWqQRtTdDnpPbBm")); + let sparsha = SPARSHA.get().unwrap(); let mut chars = text.chars(); if let (Some(x), Some(y)) = (chars.next(), chars.next()) { - if AC.contains(x) && AC.contains(y) { + if ac.contains(x) && ac.contains(y) { // Must not start with a double vowel. // But, "afRin" is acceptable. text.starts_with("afR") } else { // Initial yrlv must not be followed by sparsha. - !(YAN.contains(x) && SPARSHA.contains(y)) + !(yan.contains(x) && sparsha.contains(y)) } } else { true