melodium_engine/designer/
value.rs

1use core::fmt::{Display, Formatter, Result};
2use melodium_common::descriptor::{
3    Context, DataType, DescribedType, Function, Generic, Identifier, Parameterized, Variability,
4};
5use melodium_common::executive::Value as ExecutiveValue;
6use std::collections::HashMap;
7use std::sync::{Arc, RwLock};
8
9use crate::{LogicError, LogicResult};
10
11use super::{FunctionInstanciation, GenericInstanciation, Reference};
12
13#[derive(Clone, Debug)]
14pub enum Value {
15    Raw(ExecutiveValue),
16    Array(Vec<Value>),
17    Variable(String),
18    Context(Arc<dyn Context>, String),
19    Function(
20        Arc<dyn Function>,
21        HashMap<String, DescribedType>,
22        Vec<Value>,
23    ),
24}
25
26impl Value {
27    pub fn make_use(&self, identifier: &Identifier) -> bool {
28        match self {
29            Value::Raw(_) => false,
30            Value::Array(array) => array.iter().any(|val| val.make_use(identifier)),
31            Value::Variable(_) => false,
32            Value::Context(context, _) => context.identifier() == identifier,
33            Value::Function(function, described_types, values) => {
34                function.identifier() == identifier
35                    || described_types.iter().any(|(_, dt)| {
36                        dt.final_type()
37                            .data()
38                            .map(|data| data.identifier() == identifier)
39                            .unwrap_or(false)
40                    })
41                    || values.iter().any(|value| value.make_use(identifier))
42            }
43        }
44    }
45
46    pub fn uses(&self) -> Vec<Identifier> {
47        match self {
48            Value::Raw(_) | Value::Variable(_) => vec![],
49            Value::Array(array) => array.iter().fold(Vec::new(), |mut ids, val| {
50                let identifiers: Vec<_> = val
51                    .uses()
52                    .into_iter()
53                    .filter(|id| !ids.contains(id))
54                    .collect();
55                ids.extend(identifiers);
56                ids
57            }),
58            Value::Context(context, _) => vec![context.identifier().clone()],
59            Value::Function(function, described_types, values) => {
60                let mut uses = vec![function.identifier().clone()];
61                uses.extend(described_types.iter().filter_map(|(_, dt)| {
62                    dt.final_type().data().map(|data| data.identifier().clone())
63                }));
64                uses.extend(values.iter().flat_map(|value| value.uses()));
65                uses
66            }
67        }
68    }
69
70    pub fn check(
71        &self,
72        described_type: &DescribedType,
73        scope_descriptor: &Arc<dyn Parameterized>,
74        scope_generics: &Arc<RwLock<HashMap<String, DescribedType>>>,
75        called_id: &Identifier,
76        parent_generics: &Arc<RwLock<HashMap<String, DescribedType>>>,
77        parameter_name: &str,
78        parameter_variability: Variability,
79        design_reference: &Option<Arc<dyn Reference>>,
80    ) -> LogicResult<Variability> {
81        match self {
82            Value::Raw(data) => {
83                if described_type.is_datatype(&data.datatype(), &parent_generics.read().unwrap()) {
84                    LogicResult::new_success(Variability::Const)
85                } else {
86                    LogicResult::new_failure(LogicError::unmatching_datatype(
87                        195,
88                        scope_descriptor.identifier().clone(),
89                        called_id.clone(),
90                        parameter_name.to_string(),
91                        self.clone(),
92                        described_type.clone(),
93                        data.datatype().into(),
94                        design_reference.clone(),
95                    ))
96                }
97            }
98            Value::Array(array) => {
99                if let Some(DataType::Vec(inner_type)) =
100                    described_type.to_datatype(&parent_generics.read().unwrap())
101                {
102                    let mut result = LogicResult::new_success(());
103                    let mut variability = Variability::Const;
104                    for val in array {
105                        if let Some(var) = result.merge_degrade_failure(val.check(
106                            &DescribedType::from(&*inner_type),
107                            scope_descriptor,
108                            scope_generics,
109                            called_id,
110                            parent_generics,
111                            parameter_name,
112                            parameter_variability,
113                            design_reference,
114                        )) {
115                            if var == Variability::Var {
116                                variability = Variability::Var;
117                            }
118                        }
119                    }
120                    result.and(LogicResult::new_success(variability))
121                } else {
122                    LogicResult::new_failure(LogicError::unmatching_datatype(
123                        226,
124                        scope_descriptor.identifier().clone(),
125                        called_id.clone(),
126                        parameter_name.to_string(),
127                        self.clone(),
128                        described_type.clone(),
129                        DescribedType::Vec(Box::new(DescribedType::Generic(Box::new(
130                            Generic::new("_".to_string(), Vec::new()),
131                        )))),
132                        design_reference.clone(),
133                    ))
134                }
135            }
136            Value::Variable(name) => {
137                if let Some(scope_variable) = scope_descriptor.parameters().get(name) {
138                    let mut result = LogicResult::new_success(());
139                    if parameter_variability == Variability::Const
140                        && *scope_variable.variability() != Variability::Const
141                    {
142                        result
143                            .errors_mut()
144                            .push(LogicError::const_required_var_provided(
145                                196,
146                                scope_descriptor.identifier().clone(),
147                                called_id.clone(),
148                                parameter_name.to_string(),
149                                name.to_string(),
150                                design_reference.clone(),
151                            ));
152                    }
153
154                    if !described_type.is_compatible(
155                        &parent_generics.read().unwrap(),
156                        scope_variable.described_type(),
157                        &scope_generics.read().unwrap(),
158                    ) {
159                        result.errors_mut().push(LogicError::unmatching_datatype(
160                            197,
161                            scope_descriptor.identifier().clone(),
162                            called_id.clone(),
163                            parameter_name.to_string(),
164                            self.clone(),
165                            described_type.clone(),
166                            scope_variable.described_type().clone(),
167                            design_reference.clone(),
168                        ));
169                    }
170
171                    result.and(LogicResult::new_success(*scope_variable.variability()))
172                } else {
173                    LogicResult::new_failure(LogicError::unexisting_variable(
174                        198,
175                        scope_descriptor.identifier().clone(),
176                        parameter_name.to_string(),
177                        name.to_string(),
178                        design_reference.clone(),
179                    ))
180                }
181            }
182            Value::Context(context, name) => {
183                let mut result = LogicResult::new_success(());
184                if parameter_variability == Variability::Const {
185                    result
186                        .errors_mut()
187                        .push(LogicError::const_required_context_provided(
188                            199,
189                            scope_descriptor.identifier().clone(),
190                            called_id.clone(),
191                            parameter_name.to_string(),
192                            context.identifier().clone(),
193                            name.to_string(),
194                            design_reference.clone(),
195                        ));
196                }
197
198                if let Some(context_variable_datatype) = context.values().get(name) {
199                    if !described_type
200                        .is_datatype(context_variable_datatype, &parent_generics.read().unwrap())
201                    {
202                        result.errors_mut().push(LogicError::unmatching_datatype(
203                            200,
204                            scope_descriptor.identifier().clone(),
205                            called_id.clone(),
206                            parameter_name.to_string(),
207                            self.clone(),
208                            described_type.clone(),
209                            context_variable_datatype.into(),
210                            design_reference.clone(),
211                        ));
212                    }
213                } else {
214                    result
215                        .errors_mut()
216                        .push(LogicError::unexisting_context_variable(
217                            201,
218                            scope_descriptor.identifier().clone(),
219                            parameter_name.to_string(),
220                            context.identifier().clone(),
221                            name.clone(),
222                            design_reference.clone(),
223                        ));
224                }
225
226                result.and(LogicResult::new_success(Variability::Var))
227            }
228            Value::Function(descriptor, generics, parameters) => {
229                let mut function_instanciation = FunctionInstanciation::new(
230                    descriptor,
231                    &scope_descriptor,
232                    &scope_generics,
233                    scope_descriptor.identifier().clone(),
234                    design_reference.clone(),
235                );
236
237                let mut result = LogicResult::new_success(());
238                let mut variability = Variability::Var;
239
240                for (generic_name, r#type) in generics {
241                    result.merge_degrade_failure(
242                        function_instanciation.set_generic(generic_name.clone(), r#type.clone()),
243                    );
244                }
245
246                if let Some((sub_variability, sub_return_type)) = result
247                    .merge_degrade_failure(function_instanciation.check_function_return(parameters))
248                {
249                    if !described_type.is_compatible(
250                        &parent_generics.read().unwrap(),
251                        &sub_return_type,
252                        &generics,
253                    ) {
254                        result = result.and_degrade_failure(LogicResult::new_failure(
255                            LogicError::unmatching_datatype(
256                                217,
257                                scope_descriptor.identifier().clone(),
258                                descriptor.identifier().clone(),
259                                parameter_name.to_string(),
260                                self.clone(),
261                                described_type.clone(),
262                                sub_return_type,
263                                design_reference.clone(),
264                            ),
265                        ));
266                    }
267
268                    if parameter_variability == Variability::Const
269                        && sub_variability != Variability::Const
270                    {
271                        result = result.and_degrade_failure(LogicResult::new_failure(
272                            LogicError::const_required_function_returns_var(
273                                202,
274                                scope_descriptor.identifier().clone(),
275                                called_id.clone(),
276                                parameter_name.to_string(),
277                                descriptor.identifier().clone(),
278                                design_reference.clone(),
279                            ),
280                        ));
281                    }
282
283                    variability = sub_variability;
284                }
285                result.and(LogicResult::new_success(variability))
286            }
287        }
288    }
289}
290
291impl Display for Value {
292    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
293        match self {
294            Value::Raw(data) => write!(f, "{}", data),
295            Value::Array(array) => write!(
296                f,
297                "[{}]",
298                array
299                    .iter()
300                    .map(|v| v.to_string())
301                    .collect::<Vec<_>>()
302                    .join(", ")
303            ),
304            Value::Variable(name) => write!(f, "{}", name),
305            Value::Context(desc, entry) => write!(f, "{}[{}]", desc.name(), entry),
306            Value::Function(desc, described_types, params) => write!(
307                f,
308                "{}{}({})",
309                desc.identifier().name(),
310                if desc.generics().is_empty() {
311                    "".to_string()
312                } else {
313                    format!(
314                        "<{}>",
315                        desc.generics()
316                            .iter()
317                            .map(|gen| if let Some(val) = described_types.get(&gen.name) {
318                                val.to_string()
319                            } else {
320                                "_".to_string()
321                            })
322                            .collect::<Vec<_>>()
323                            .join(", ")
324                    )
325                },
326                params
327                    .iter()
328                    .map(|p| p.to_string())
329                    .collect::<Vec<_>>()
330                    .join(", ")
331            ),
332        }
333    }
334}
335
336impl From<ExecutiveValue> for Value {
337    fn from(value: ExecutiveValue) -> Self {
338        Value::Raw(value)
339    }
340}
341
342impl From<&ExecutiveValue> for Value {
343    fn from(value: &ExecutiveValue) -> Self {
344        Value::Raw(value.clone())
345    }
346}