bc_envelope/extension/expressions/
parameters.rs

1use std::sync::{Once, Mutex};
2use paste::paste;
3
4use super::{Parameter, ParametersStore};
5
6/// A macro that declares a parameter at compile time.
7///
8/// This macro generates a constant `Parameter` with a given numeric value and name.
9/// It also creates a companion constant for the numeric value with a suffix `_VALUE`.
10///
11/// # Examples
12///
13/// ```ignore
14/// use bc_envelope::prelude::*;
15/// use bc_envelope::parameter_constant;
16/// use bc_envelope::extension::expressions::Parameter;
17///
18/// // Define a custom parameter
19/// parameter_constant!(MY_PARAM, 100, "myParam");
20///
21/// // Usage
22/// assert_eq!(MY_PARAM_VALUE, 100);
23/// assert_eq!(MY_PARAM.name(), "myParam");
24/// ```
25#[macro_export]
26macro_rules! parameter_constant {
27    ($const_name:ident, $value:expr, $name:expr) => {
28        paste! {
29            pub const [<$const_name _VALUE>]: u64 = $value;
30        }
31        pub const $const_name: Parameter = Parameter::new_with_static_name($value, $name);
32    };
33}
34
35// The blank parameter, used for single-parameter functions.
36//
37// This parameter is commonly used when a function needs only one parameter
38// and the parameter's purpose is clear from context. It is denoted as `❰_❱`
39// in envelope notation.
40parameter_constant!(BLANK, 1, "_");
41
42// The left-hand side parameter, used for binary operations.
43//
44// This parameter typically represents the first operand in a binary operation
45// such as addition or multiplication.
46parameter_constant!(LHS, 2, "lhs");
47
48// The right-hand side parameter, used for binary operations.
49//
50// This parameter typically represents the second operand in a binary operation
51// such as addition or multiplication.
52parameter_constant!(RHS, 3, "rhs");
53
54/// A helper type for lazy initialization of the global parameters store.
55///
56/// This is an implementation detail that handles thread-safe, one-time
57/// initialization of the global parameters registry.
58#[doc(hidden)]
59#[derive(Debug)]
60pub struct LazyParameters {
61    init: Once,
62    data: Mutex<Option<ParametersStore>>,
63}
64
65impl LazyParameters {
66    /// Gets a reference to the global parameters store, initializing it if necessary.
67    ///
68    /// This method ensures the global parameters store is initialized only once,
69    /// in a thread-safe manner.
70    ///
71    /// # Returns
72    ///
73    /// A mutex guard containing a reference to the parameters store
74    pub fn get(&self) -> std::sync::MutexGuard<'_, Option<ParametersStore>> {
75        self.init.call_once(|| {
76            let m = ParametersStore::new([
77                BLANK,
78                LHS,
79                RHS,
80            ]);
81            *self.data.lock().unwrap() = Some(m);
82        });
83        self.data.lock().unwrap()
84    }
85}
86
87/// The global shared store of known parameters.
88///
89/// This provides access to a global registry of standard parameters used
90/// in envelope expressions. It is lazily initialized the first time it's accessed.
91///
92/// # Examples
93///
94/// ```
95/// use bc_envelope::prelude::*;
96/// use bc_envelope::extension::expressions::{parameters, GLOBAL_PARAMETERS};
97///
98/// // Access the global parameters store
99/// let parameters_store = GLOBAL_PARAMETERS.get();
100/// if let Some(store) = &*parameters_store {
101///     // Use the store to look up parameter names
102///     assert_eq!(store.name(&parameters::LHS), "lhs");
103/// }
104/// ```
105pub static GLOBAL_PARAMETERS: LazyParameters = LazyParameters {
106    init: Once::new(),
107    data: Mutex::new(None),
108};