microcad_lang/eval/
parameter.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Parameter evaluation entity
5
6use crate::{eval::*, syntax::*, ty::*, value::*};
7
8impl Eval<ParameterValue> for Parameter {
9    /// Evaluate [Parameter] into [ParameterValue].
10    fn eval(&self, context: &mut Context) -> EvalResult<ParameterValue> {
11        match (&self.specified_type, &self.default_value) {
12            // Type and value are specified
13            (Some(specified_type), Some(default_value)) => {
14                let default_value: Value = default_value.eval(context)?;
15                if specified_type.ty() != default_value.ty() {
16                    context.error(
17                        self,
18                        EvalError::TypeMismatch {
19                            id: self.id.clone(),
20                            expected: specified_type.ty(),
21                            found: default_value.ty(),
22                        },
23                    )?;
24                    // Return an invalid parameter value in case evaluation failed
25                    Ok(ParameterValue::invalid(self.src_ref()))
26                } else {
27                    Ok(ParameterValue {
28                        specified_type: Some(specified_type.ty()),
29                        default_value: Some(default_value),
30                        src_ref: self.src_ref(),
31                    })
32                }
33            }
34            // Only type is specified
35            (Some(t), None) => Ok(ParameterValue {
36                specified_type: Some(t.ty()),
37                src_ref: self.src_ref(),
38                ..Default::default()
39            }),
40            // Only value is specified
41            (None, Some(expr)) => {
42                let default_value: Value = expr.eval(context)?;
43
44                Ok(ParameterValue {
45                    specified_type: Some(default_value.ty().clone()),
46                    default_value: Some(default_value),
47                    src_ref: self.src_ref(),
48                })
49            }
50            // Neither type nor value is specified
51            (None, None) => Ok(ParameterValue::invalid(self.src_ref())),
52        }
53    }
54}
55
56impl Eval<ParameterValueList> for ParameterList {
57    /// Evaluate [ParameterList] into [ParameterValueList].
58    fn eval(&self, context: &mut Context) -> EvalResult<ParameterValueList> {
59        let mut values = ParameterValueList::default();
60        for parameter in self.iter() {
61            values.insert(parameter.id.clone(), parameter.eval(context)?)?;
62        }
63
64        Ok(values)
65    }
66}