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}