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