melodium_engine/designer/
parameter.rs1use super::{Reference, Scope, Value};
2use crate::design::Parameter as ParameterDesign;
3use crate::error::{LogicError, LogicResult};
4use melodium_common::descriptor::{Collection, DescribedType, Entry, Identifier, Parameterized};
5use std::collections::HashMap;
6use std::sync::{Arc, RwLock, Weak};
7
8#[derive(Debug)]
9pub struct Parameter {
10 scope: Weak<RwLock<dyn Scope>>,
11 scope_descriptor: Weak<dyn Parameterized>,
12 scope_generics: Arc<RwLock<HashMap<String, DescribedType>>>,
13 scope_id: Identifier,
14 parent_descriptor: Weak<dyn Parameterized>,
15 parent_generics: Arc<RwLock<HashMap<String, DescribedType>>>,
16 name: String,
17 value: Option<Value>,
18 design_reference: Option<Arc<dyn Reference>>,
19}
20
21impl Parameter {
22 pub fn new(
23 scope: &Arc<RwLock<dyn Scope>>,
24 scope_descriptor: &Arc<dyn Parameterized>,
25 scope_generics: &Arc<RwLock<HashMap<String, DescribedType>>>,
26 scope_id: Identifier,
27 parent_descriptor: &Arc<dyn Parameterized>,
28 parent_generics: &Arc<RwLock<HashMap<String, DescribedType>>>,
29 name: &str,
30 design_reference: Option<Arc<dyn Reference>>,
31 ) -> Self {
32 Self {
33 scope: Arc::downgrade(scope),
34 scope_descriptor: Arc::downgrade(scope_descriptor),
35 scope_generics: Arc::clone(scope_generics),
36 scope_id,
37 parent_descriptor: Arc::downgrade(parent_descriptor),
38 parent_generics: Arc::clone(parent_generics),
39 name: name.to_string(),
40 value: None,
41 design_reference,
42 }
43 }
44
45 pub fn scope(&self) -> &Weak<RwLock<dyn Scope>> {
46 &self.scope
47 }
48
49 pub fn parent_descriptor(&self) -> &Weak<dyn Parameterized> {
50 &self.parent_descriptor
51 }
52
53 pub fn design_reference(&self) -> &Option<Arc<dyn Reference>> {
54 &self.design_reference
55 }
56
57 pub(crate) fn import_design(
58 &mut self,
59 design: &ParameterDesign,
60 collection: &Arc<Collection>,
61 replace: &HashMap<Identifier, Identifier>,
62 ) -> LogicResult<()> {
63 fn import_value(
64 value: &Value,
65 design: &ParameterDesign,
66 collection: &Arc<Collection>,
67 replace: &HashMap<Identifier, Identifier>,
68 scope_id: &Identifier,
69 design_reference: &Option<Arc<dyn Reference>>,
70 ) -> Result<Value, LogicError> {
71 match value {
72 Value::Raw(executive_value) => Ok(Value::Raw(executive_value.clone())),
73 Value::Array(array) => {
74 let mut new_array = Vec::with_capacity(array.len());
75 for val in array {
76 match import_value(
77 val,
78 design,
79 collection,
80 replace,
81 scope_id,
82 design_reference,
83 ) {
84 Ok(val) => new_array.push(val),
85 Err(err) => return Err(err),
86 }
87 }
88 Ok(Value::Array(new_array))
89 }
90 Value::Variable(variable) => Ok(Value::Variable(variable.clone())),
91 Value::Context(former_context, entry) => {
92 if let Some(Entry::Context(new_context)) = collection.get(
93 &replace
94 .get(former_context.identifier())
95 .unwrap_or_else(|| former_context.identifier())
96 .into(),
97 ) {
98 Ok(Value::Context(new_context.clone(), entry.clone()))
99 } else {
100 Err(LogicError::unexisting_context(
101 204,
102 scope_id.clone(),
103 former_context.identifier().into(),
104 design_reference.clone(),
105 ))
106 }
107 }
108 Value::Function(former_function, generics, values) => {
109 if let Some(Entry::Function(new_function)) = collection.get(
110 &replace
111 .get(former_function.identifier())
112 .unwrap_or_else(|| former_function.identifier())
113 .into(),
114 ) {
115 Ok(Value::Function(
116 new_function.clone(),
117 generics.clone(),
118 values.clone(),
119 ))
120 } else {
121 Err(LogicError::unexisting_function(
122 205,
123 scope_id.clone(),
124 former_function.identifier().into(),
125 design_reference.clone(),
126 ))
127 }
128 }
129 }
130 }
131
132 let value = import_value(
133 &design.value,
134 design,
135 collection,
136 replace,
137 &self.scope_id,
138 &self.design_reference,
139 );
140
141 match value {
142 Ok(value) => self.set_value(value),
143 Err(err) => LogicResult::new_failure(err),
144 }
145 }
146
147 pub fn name(&self) -> &str {
148 &self.name
149 }
150
151 pub fn set_value(&mut self, value: Value) -> LogicResult<()> {
152 let parent_descriptor = self.parent_descriptor.upgrade().unwrap();
153 let parameter = parent_descriptor.parameters().get(&self.name);
154 if let Some(parameter) = parameter {
155 let result = value.check(
156 parameter.described_type(),
157 &self.scope_descriptor.upgrade().unwrap(),
158 &self.scope_generics,
159 self.parent_descriptor.upgrade().unwrap().identifier(),
160 &self.parent_generics,
161 parameter.name(),
162 *parameter.variability(),
163 &self.design_reference,
164 );
165
166 if result.is_success() {
167 self.value = Some(value.clone());
168 }
169 result.and(LogicResult::new_success(()))
170 } else {
171 LogicResult::new_success(())
172 }
173 }
174
175 pub fn value(&self) -> &Option<Value> {
176 &self.value
177 }
178
179 pub fn described_type(&self) -> LogicResult<Option<DescribedType>> {
180 let parent_descriptor = self.parent_descriptor.upgrade().unwrap();
181 let parameter = parent_descriptor.parameters().get(&self.name);
182 match parameter.map(|parameter| {
183 parameter
184 .described_type()
185 .as_defined(&self.parent_generics.read().unwrap())
186 .ok_or_else(|| -> LogicResult<Option<DescribedType>> {
187 LogicResult::new_failure(LogicError::undefined_generic(
188 221,
189 self.scope_id.clone(),
190 parent_descriptor.identifier().clone(),
191 parameter.described_type().clone(),
192 self.design_reference.clone(),
193 ))
194 })
195 }) {
196 Some(described_type) => match described_type {
197 Ok(described_type) => LogicResult::new_success(Some(described_type)),
198 Err(err) => err,
199 },
200 None => LogicResult::new_success(None),
201 }
202 }
203
204 pub fn validate(&self) -> LogicResult<()> {
205 let mut result = LogicResult::new_success(());
206
207 let parent_descriptor = self.parent_descriptor.upgrade().unwrap();
208 let parameter = parent_descriptor.parameters().get(&self.name);
209
210 if self.value.is_none() {
211 result.errors_mut().push(LogicError::no_value(
212 27,
213 self.scope_id.clone(),
214 parent_descriptor.identifier().clone(),
215 self.name.clone(),
216 self.design_reference.clone(),
217 ));
218 }
219
220 if let Some(parameter) = parameter {
222 if let Some(value) = self.value.as_ref() {
223 result = result
224 .and_degrade_failure(value.check(
225 parameter.described_type(),
226 &self.scope_descriptor.upgrade().unwrap(),
227 &self.scope_generics,
228 self.parent_descriptor.upgrade().unwrap().identifier(),
229 &self.parent_generics,
230 parameter.name(),
231 *parameter.variability(),
232 &self.design_reference,
233 ))
234 .and(LogicResult::new_success(()));
235 } else {
236 result.errors_mut().push(LogicError::no_value(
237 27,
238 self.scope_id.clone(),
239 self.parent_descriptor
240 .upgrade()
241 .unwrap()
242 .identifier()
243 .clone(),
244 self.name.clone(),
245 self.design_reference.clone(),
246 ));
247 }
248 } else {
249 result.errors_mut().push(LogicError::unexisting_parameter(
250 194,
251 self.scope_id.clone(),
252 parent_descriptor.identifier().clone(),
253 self.name.clone(),
254 self.design_reference.clone(),
255 ));
256 }
257
258 result
259 }
260}