microcad_lang/syntax/parameter/
mod.rs

1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! µcad parameter syntax elements
5
6mod parameter_list;
7
8use crate::{diag::*, eval::*, ord_map::*, src_ref::*, syntax::*, ty::*, value::*};
9
10pub use parameter_list::*;
11
12/// A parameter of a parameter list.
13#[derive(Clone, Debug, Default)]
14pub struct Parameter {
15    /// Name of the parameter
16    pub id: Identifier,
17    /// Type of the parameter or `None`
18    pub specified_type: Option<TypeAnnotation>,
19    /// default value of the parameter or `None`
20    pub default_value: Option<Expression>,
21    /// Source code reference
22    pub src_ref: SrcRef,
23}
24
25impl Parameter {
26    /// Create new parameter
27    pub fn new(
28        id: Identifier,
29        specified_type: Option<TypeAnnotation>,
30        default_value: Option<Expression>,
31        src_ref: SrcRef,
32    ) -> Self {
33        assert!(!id.is_empty());
34        Self {
35            id,
36            specified_type,
37            default_value,
38            src_ref,
39        }
40    }
41
42    /// Create a new parameter without any SrcRef's
43    pub fn no_ref(id: &str, ty: Type) -> Self {
44        Self {
45            id: Identifier::no_ref(id),
46            specified_type: Some(TypeAnnotation(Refer::none(ty))),
47            default_value: None,
48            src_ref: SrcRef(None),
49        }
50    }
51
52    /// Evaluate default value considering specified type
53    ///
54    /// If there is no default value, returns `Value::None` without raising an error.
55    pub fn eval_default_value(&self, context: &mut Context) -> crate::eval::EvalResult<Value> {
56        use crate::eval::Eval;
57
58        match (&self.specified_type, &self.default_value) {
59            (Some(specified_type), Some(default_value)) => {
60                let value: Value = default_value.eval(context)?;
61                if specified_type.ty() != value.ty() {
62                    context.error(
63                        &self.src_ref,
64                        EvalError::TypeMismatch {
65                            id: self.id.clone(),
66                            expected: specified_type.ty(),
67                            found: value.ty(),
68                        },
69                    )?;
70                    Ok(Value::None)
71                } else {
72                    Ok(value)
73                }
74            }
75            (None, Some(default_value)) => Ok(default_value.eval(context)?),
76            _ => Ok(Value::None),
77        }
78    }
79}
80
81impl SrcReferrer for Parameter {
82    fn src_ref(&self) -> SrcRef {
83        self.src_ref.clone()
84    }
85}
86
87impl OrdMapValue<Identifier> for Parameter {
88    fn key(&self) -> Option<Identifier> {
89        Some(self.id.clone())
90    }
91}
92
93impl std::fmt::Display for Parameter {
94    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
95        match (&self.specified_type, &self.default_value) {
96            (Some(t), Some(v)) => write!(f, "{}: {t} = {v}", self.id),
97            (Some(t), None) => write!(f, "{}: {t}", self.id),
98            (None, Some(v)) => write!(f, "{} = {v}", self.id),
99            _ => Ok(()),
100        }
101    }
102}
103
104impl TreeDisplay for Parameter {
105    fn tree_print(&self, f: &mut std::fmt::Formatter, depth: TreeState) -> std::fmt::Result {
106        match (&self.specified_type, &self.default_value) {
107            (Some(specified_type), Some(default_value)) => writeln!(
108                f,
109                "{:depth$}Parameter: {}: {} = {}",
110                "", self.id, specified_type, default_value
111            ),
112            (Some(specified_type), None) => {
113                writeln!(f, "{:depth$}Parameter: {}: {}", "", self.id, specified_type)
114            }
115            (None, Some(default_value)) => {
116                writeln!(f, "{:depth$}Parameter: {} = {}", "", self.id, default_value)
117            }
118            _ => unreachable!("impossible parameter declaration"),
119        }
120    }
121}