synthphonia/expr/ops/list/
map.rs

1use std::cmp::min;
2use std::ops::Not;
3
4use crate::expr::context::Context;
5use crate::expr::Expr;
6use crate::galloc::{AllocForExactSizeIter, AllocForStr, TryAllocForExactSizeIter};
7use crate::parser::config::Config;
8use crate::utils::F64;
9use crate::{impl_op2, new_op1, new_op2, new_op2_opt, new_op3};
10use derive_more::DebugCustom;
11use itertools::izip;
12use crate::value::Value;
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14/// A struct representing a mapping configuration for expressions. 
15/// 
16/// This structure contains a single field, an optional reference to a static `Expr` instance. 
17/// The `Option` type encapsulates the possibility of this reference being `None`, indicating that the mapping may or may not point to a valid expression at any given time. 
18/// This flexibility allows for dynamic adjustments within the synthesis process, where certain mappings might be deferred or omitted based on the current context or requirements.
19/// 
20pub struct Map(pub Option<&'static Expr>);
21
22impl std::hash::Hash for Map {
23    /// Provides a method to calculate the hash of the `Map` structure. 
24    /// 
25    /// The method takes a mutable reference to a generic hasher `H` and computes the hash by first accessing the internal `Option<&'static Expr>` value. 
26    /// If the `Option` is `Some`, it maps the contained expression reference to a raw pointer and incorporates it into the hash calculation. 
27    /// This ensures that the hashing process uniquely accounts for the memory address of the expression's reference, enhancing the precision of hash-based collections or algorithms using `Map` instances.
28    /// 
29    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
30        self.0.map(|x| x as *const Expr).hash(state);
31    }
32}
33
34impl Map {
35    /// Creates a `Map` instance using the provided configuration. 
36    /// 
37    /// It retrieves an expression associated with the key `"f"` from the given `Config` object, which may be `None` if the key is not found, and wraps this expression in a `Map`. 
38    /// This function assists in initializing a `Map` based on pre-defined configurations, facilitating customizable synthesis processes.
39    /// 
40    pub fn from_config(config: &Config) -> Self {
41        Self(config.get_expr("f"))
42    }
43    /// Provides a method to retrieve the name associated with the `Map`. 
44    /// 
45    /// It returns a static string slice representing the operation's name within the context of the Synthphonia module, specifically identifying the `list.map` functionality. 
46    /// This method is likely used to ensure consistency and readability when referring to the mapping operation internally or in debug outputs.
47    /// 
48    pub fn name() ->  &'static str {
49        "list.map"
50    }
51}
52
53impl std::fmt::Display for Map {
54    /// Formats the `Map` structure for output. 
55    /// 
56    /// The function checks if the `Map` contains an `Expr` and, if so, formats the output to include the expression with a "list.map" prefix decorated by the expression's debug representation. 
57    /// If no expression is present, the output simply includes "list.map". 
58    /// This functionality is useful for logging or debugging when visual representation of the mapping operation is required.
59    /// 
60    fn fmt(&self,f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        if let Some(e) = self.0 {
62            write!(f, "list.map #f:{:?}", e)
63        } else {
64            write!(f, "list.map")
65        }
66    }
67}
68impl Default for Map {
69    /// Creates a default instance of the type by invoking the `from_config` method with a default configuration. 
70    /// This method serves as a convenient way to generate an instance with standard settings, ensuring that if no specific configuration is provided, the type is still initialized in a consistent manner using default parameters.
71    fn default() -> Self {
72        Self::from_config(&Default::default())
73    }
74}
75
76impl crate::forward::enumeration::Enumerator1 for Map {
77    /// Provides a method for the `Map` structure to perform enumeration with given parameters, but currently returns a placeholder result. 
78    /// 
79    /// This method, `enumerate`, takes as parameters a reference to an instance of `Op1Enum`, a static reference to an `Executor`, and an array of one usize operand. 
80    /// However, in its current implementation, it performs no actual enumeration or transformation logic and immediately returns a successful `Result` wrapped in `Ok(())` with an empty tuple as the error state. 
81    /// This suggests that further enhancements or a use-case-specific implementation might be forthcoming for this structure within the application's context.
82    /// 
83    fn enumerate(&self, this: &'static crate::expr::ops::Op1Enum, exec: &'static crate::forward::executor::Executor, opnt: [usize; 1]) -> Result<(), ()> { Ok(()) }
84}
85
86impl crate::expr::ops::Op1 for Map {
87    /// Calculates and returns the cost of the operation as a constant value. 
88    /// 
89    /// In this implementation, the method consistently returns `1`, indicating a fixed cost for any instance of the struct, regardless of the contents of the `Option<&'static Expr>` field. 
90    /// This could be useful for basic cost computation scenarios where each `Map` instance contributes a uniform cost in the overall synthesis process.
91    /// 
92    fn cost(&self) -> usize { 1 }
93    /// Provides a method to evaluate an expression contained within a `Map` structure using a given `Value`. 
94    /// 
95    /// If the input `Value` is of the type `ListStr`, it iterates over the list, creating a context for each string element that includes the length of the string and the string itself. 
96    /// The expression is then evaluated within this context, converting the result to a string. 
97    /// The output `Value` is adjusted to be a collection of these string results, and the method returns a tuple indicating success with a `true` boolean and the resultant `Value`. 
98    /// If the input `Value` is not a `ListStr`, the method returns `false` and a `Null` `Value`.
99    /// 
100    fn try_eval(&self, a1: Value) -> (bool, Value) {
101        let e = self.0.unwrap();
102        if let Value::ListStr(a) = a1 {
103            let a = a.iter().map(|&x| {
104                let ctx = Context::new(x.len(), vec![x.into()], vec![], Value::Null);
105                e.eval(&ctx).to_str()
106            }).galloc_scollect();
107            (true, a.into())
108        } else { (false, Value::Null)}
109    }
110}