melodium_engine/designer/
function_instanciation.rs

1use super::{GenericInstanciation, Reference, Value};
2use crate::{LogicError, LogicResult};
3use melodium_common::descriptor::{
4    DataTrait, DescribedType, Function as FunctionDescriptor, Identifier, Parameterized,
5    Variability,
6};
7use std::{
8    collections::HashMap,
9    sync::{Arc, RwLock, RwLockReadGuard, Weak},
10};
11
12#[derive(Debug)]
13pub struct FunctionInstanciation {
14    descriptor: Weak<dyn FunctionDescriptor>,
15    scope_descriptor: Weak<dyn Parameterized>,
16    scope_generics: Arc<RwLock<HashMap<String, DescribedType>>>,
17    scope_id: Identifier,
18    generics: Arc<RwLock<HashMap<String, DescribedType>>>,
19    design_reference: Option<Arc<dyn Reference>>,
20}
21
22impl FunctionInstanciation {
23    pub fn new(
24        descriptor: &Arc<dyn FunctionDescriptor>,
25        scope_descriptor: &Arc<dyn Parameterized>,
26        scope_generics: &Arc<RwLock<HashMap<String, DescribedType>>>,
27        scope_id: Identifier,
28        design_reference: Option<Arc<dyn Reference>>,
29    ) -> Self {
30        Self {
31            descriptor: Arc::downgrade(descriptor),
32            scope_descriptor: Arc::downgrade(scope_descriptor),
33            scope_generics: Arc::clone(scope_generics),
34            scope_id,
35            generics: Arc::new(RwLock::new(HashMap::with_capacity(
36                descriptor.generics().len(),
37            ))),
38            design_reference,
39        }
40    }
41
42    pub fn descriptor(&self) -> Arc<dyn FunctionDescriptor> {
43        self.descriptor.upgrade().unwrap()
44    }
45
46    pub fn check_function_return(
47        &self,
48        parameters: &Vec<Value>,
49    ) -> LogicResult<(Variability, DescribedType)> {
50        let descriptor = self.descriptor();
51
52        let mut result = LogicResult::new_success(());
53        let mut variability = Variability::Const;
54
55        if descriptor.parameters().len() != parameters.len() {
56            result
57                .errors_mut()
58                .push(LogicError::unmatching_number_of_parameters(
59                    64,
60                    self.scope_id.clone(),
61                    descriptor.identifier().clone(),
62                    self.design_reference.clone(),
63                ));
64        }
65
66        for i in 0..usize::min(descriptor.parameters().len(), parameters.len()) {
67            let param_descriptor = &descriptor.parameters()[i];
68            if let Some(var) = result.merge_degrade_failure(parameters[i].check(
69                param_descriptor.described_type(),
70                &self.scope_descriptor.upgrade().unwrap(),
71                &self.scope_generics,
72                descriptor.identifier(),
73                &self.generics,
74                param_descriptor.name(),
75                *param_descriptor.variability(),
76                &self.design_reference,
77            )) {
78                if var == Variability::Var {
79                    variability = Variability::Var;
80                }
81            }
82        }
83
84        result.and_then(|_| {
85            if let Some(described_type) = descriptor
86                .return_type()
87                .as_defined(&self.generics.read().unwrap())
88            {
89                LogicResult::new_success((variability, described_type))
90            } else {
91                LogicResult::new_failure(LogicError::undefined_generic(
92                    215,
93                    self.scope_id.clone(),
94                    descriptor.identifier().clone(),
95                    descriptor.return_type().clone(),
96                    self.design_reference.clone(),
97                ))
98            }
99        })
100    }
101}
102
103impl GenericInstanciation for FunctionInstanciation {
104    fn generics(&'_ self) -> RwLockReadGuard<'_, HashMap<String, DescribedType>> {
105        self.generics.read().unwrap()
106    }
107
108    fn set_generic(&mut self, generic_name: String, r#type: DescribedType) -> LogicResult<()> {
109        let descriptor = self.descriptor();
110        if let Some(generic) = descriptor
111            .generics()
112            .iter()
113            .find(|gen| gen.name == generic_name)
114        {
115            if let Some(r#type) = r#type.as_defined(&self.scope_generics.read().unwrap()) {
116                let unimplemented: Vec<DataTrait> = generic
117                    .traits
118                    .iter()
119                    .filter(|tr| !r#type.implements(tr))
120                    .map(|dt| *dt)
121                    .collect();
122                if unimplemented.is_empty() {
123                    self.generics.write().unwrap().insert(generic_name, r#type);
124                    LogicResult::new_success(())
125                } else {
126                    LogicResult::new_failure(LogicError::unsatisfied_traits(
127                        222,
128                        self.scope_id.clone(),
129                        descriptor.identifier().clone(),
130                        r#type,
131                        unimplemented,
132                        self.design_reference.clone(),
133                    ))
134                }
135            } else {
136                LogicResult::new_failure(LogicError::unexisting_generic(
137                    229,
138                    self.scope_id.clone(),
139                    descriptor.identifier().clone(),
140                    generic_name,
141                    r#type,
142                    self.design_reference.clone(),
143                ))
144            }
145        } else {
146            LogicResult::new_failure(LogicError::unexisting_generic(
147                218,
148                self.scope_id.clone(),
149                descriptor.identifier().clone(),
150                generic_name,
151                r#type,
152                self.design_reference.clone(),
153            ))
154        }
155    }
156}