melodium_engine/designer/
function_instanciation.rs1use 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}