microcad_lang/syntax/parameter/
mod.rs1mod parameter_list;
7
8use crate::{eval::*, ord_map::*, syntax::*, ty::*, value::*};
9
10use microcad_lang_base::{PushDiag, Refer, SrcRef, SrcReferrer, TreeDisplay, TreeState};
11pub use parameter_list::*;
12
13#[derive(Clone, Default)]
15pub struct Parameter {
16 pub(crate) id: Identifier,
18 pub specified_type: Option<TypeAnnotation>,
20 pub default_value: Option<Expression>,
22 pub src_ref: SrcRef,
24}
25
26impl Parameter {
27 pub fn new(
29 id: Identifier,
30 specified_type: Option<TypeAnnotation>,
31 default_value: Option<Expression>,
32 src_ref: SrcRef,
33 ) -> Self {
34 assert!(!id.is_empty());
35 Self {
36 id,
37 specified_type,
38 default_value,
39 src_ref,
40 }
41 }
42
43 pub fn no_ref(id: &str, ty: Type) -> Self {
45 Self {
46 id: Identifier::no_ref(id),
47 specified_type: Some(TypeAnnotation(Refer::none(ty))),
48 default_value: None,
49 src_ref: SrcRef(None),
50 }
51 }
52
53 pub fn eval_default_value(&self, context: &mut EvalContext) -> crate::eval::EvalResult<Value> {
57 use crate::eval::Eval;
58
59 match (&self.specified_type, &self.default_value) {
60 (Some(specified_type), Some(default_value)) => {
61 let value: Value = default_value.eval(context)?;
62 if specified_type.ty() != value.ty() {
63 context.error(
64 &self.src_ref,
65 EvalError::TypeMismatch {
66 id: self.id(),
67 expected: specified_type.ty(),
68 found: value.ty(),
69 },
70 )?;
71 Ok(Value::None)
72 } else {
73 Ok(value)
74 }
75 }
76 (None, Some(default_value)) => Ok(default_value.eval(context)?),
77 _ => Ok(Value::None),
78 }
79 }
80}
81
82impl Identifiable for Parameter {
83 fn id_ref(&self) -> &Identifier {
84 &self.id
85 }
86}
87
88impl SrcReferrer for Parameter {
89 fn src_ref(&self) -> SrcRef {
90 self.src_ref.clone()
91 }
92}
93
94impl OrdMapValue<Identifier> for Parameter {
95 fn key(&self) -> Option<Identifier> {
96 Some(self.id())
97 }
98}
99
100impl std::fmt::Display for Parameter {
101 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
102 match (&self.specified_type, &self.default_value) {
103 (Some(t), Some(v)) => write!(f, "{}: {t} = {v}", self.id),
104 (Some(t), None) => write!(f, "{}: {t}", self.id),
105 (None, Some(v)) => write!(f, "{} = {v}", self.id),
106 _ => Ok(()),
107 }
108 }
109}
110
111impl std::fmt::Debug for Parameter {
112 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
113 match (&self.specified_type, &self.default_value) {
114 (Some(t), Some(v)) => write!(f, "{:?}: {t:?} = {v:?}", self.id),
115 (Some(t), None) => write!(f, "{:?}: {t:?}", self.id),
116 (None, Some(v)) => write!(f, "{:?} = {v:?}", self.id),
117 _ => Ok(()),
118 }
119 }
120}
121
122impl TreeDisplay for Parameter {
123 fn tree_print(&self, f: &mut std::fmt::Formatter, depth: TreeState) -> std::fmt::Result {
124 match (&self.specified_type, &self.default_value) {
125 (Some(specified_type), Some(default_value)) => writeln!(
126 f,
127 "{:depth$}Parameter: {}: {} = {}",
128 "", self.id, specified_type, default_value
129 ),
130 (Some(specified_type), None) => {
131 writeln!(f, "{:depth$}Parameter: {}: {}", "", self.id, specified_type)
132 }
133 (None, Some(default_value)) => {
134 writeln!(f, "{:depth$}Parameter: {} = {}", "", self.id, default_value)
135 }
136 _ => unreachable!("impossible parameter declaration"),
137 }
138 }
139}