Skip to main content

microcad_lang/eval/
parameter.rs

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