1use crate::{eval::*, model::*};
5
6impl Eval for RangeFirst {
7 fn eval(&self, context: &mut Context) -> EvalResult<Value> {
8 let value: Value = self.0.eval(context)?;
9 Ok(match value {
10 Value::Integer(_) => value,
11 value => {
12 context.error(
13 self,
14 EvalError::ExpectedType {
15 expected: Type::Integer,
16 found: value.ty(),
17 },
18 )?;
19
20 Value::None
21 }
22 })
23 }
24}
25
26impl Eval for RangeLast {
27 fn eval(&self, context: &mut Context) -> EvalResult<Value> {
28 let value: Value = self.0.eval(context)?;
29 Ok(match value {
30 Value::Integer(_) => value,
31 value => {
32 context.error(
33 self,
34 EvalError::ExpectedType {
35 expected: Type::Integer,
36 found: value.ty(),
37 },
38 )?;
39
40 Value::None
41 }
42 })
43 }
44}
45
46impl Eval for RangeExpression {
47 fn eval(&self, context: &mut Context) -> EvalResult<Value> {
48 Ok(
49 match (self.first.eval(context)?, self.last.eval(context)?) {
50 (Value::Integer(first), Value::Integer(last)) => Value::Array(Array::new(
51 (first..last + 1).map(Value::Integer).collect(),
52 Type::Integer,
53 )),
54 (_, _) => Value::None,
55 },
56 )
57 }
58}
59
60impl Eval for ArrayExpression {
61 fn eval(&self, context: &mut Context) -> EvalResult<Value> {
62 match &self.inner {
63 ArrayExpressionInner::Range(range_expression) => range_expression.eval(context),
64 ArrayExpressionInner::List(expressions) => {
65 let value_list = ValueList::new(
66 expressions
67 .iter()
68 .map(|expr| expr.eval(context))
69 .collect::<Result<_, _>>()?,
70 );
71
72 match value_list.types().common_type() {
73 Some(common_type) => {
74 match Value::Array(Array::new(value_list, common_type)) * self.unit {
75 Ok(value) => Ok(value),
76 Err(err) => {
77 context.error(self, err)?;
78 Ok(Value::None)
79 }
80 }
81 }
82 None => {
83 context.error(
84 self,
85 EvalError::ArrayElementsDifferentTypes(value_list.types()),
86 )?;
87 Ok(Value::None)
88 }
89 }
90 }
91 }
92 }
93}
94
95impl Eval<Option<Symbol>> for QualifiedName {
96 fn eval(&self, context: &mut Context) -> EvalResult<Option<Symbol>> {
97 match context.lookup(self) {
98 Ok(symbol) => Ok(Some(symbol.clone())),
99 Err(error) => {
100 context.error(self, error)?;
101 Ok(None)
102 }
103 }
104 }
105}
106
107impl Eval for QualifiedName {
108 fn eval(&self, context: &mut Context) -> EvalResult<Value> {
109 match &context.lookup(self)?.borrow().def {
110 SymbolDefinition::Constant(.., value) | SymbolDefinition::Argument(_, value) => {
111 Ok(value.clone())
112 }
113 SymbolDefinition::Module(ns) => Err(EvalError::UnexpectedNested("mod", ns.id.clone())),
114 SymbolDefinition::Workbench(w) => {
115 Err(EvalError::UnexpectedNested(w.kind.as_str(), w.id.clone()))
116 }
117 SymbolDefinition::Function(f) => {
118 Err(EvalError::UnexpectedNested("function", f.id.clone()))
119 }
120 SymbolDefinition::Builtin(bm) => {
121 Err(EvalError::UnexpectedNested("builtin", bm.id.clone()))
122 }
123 SymbolDefinition::Alias(_, id, _) => {
124 unreachable!("Unexpected alias {id} in expression")
125 }
126 SymbolDefinition::SourceFile(sf) => {
127 unreachable!(
128 "Unexpected source file {} in expression",
129 sf.filename_as_str()
130 )
131 }
132 SymbolDefinition::UseAll(_, name) => {
133 unreachable!("Unexpected use {name} in expression")
134 }
135 #[cfg(test)]
136 SymbolDefinition::Tester(..) => {
137 unreachable!()
138 }
139 }
140 }
141}
142
143impl Expression {
144 pub fn eval_with_attribute_list(
149 &self,
150 attribute_list: &AttributeList,
151 context: &mut Context,
152 ) -> EvalResult<Value> {
153 let value = self.eval(context)?;
154 match value {
155 Value::Model(model) => {
156 let attributes = attribute_list.eval(context)?;
157 model.borrow_mut().attributes = attributes.clone();
158 Ok(Value::Model(model))
159 }
160 Value::None => Ok(Value::None),
161 _ => {
162 if !attribute_list.is_empty() {
163 context.error(
164 attribute_list,
165 AttributeError::CannotAssignAttribute(self.clone().into()),
166 )?;
167 }
168 Ok(value)
169 }
170 }
171 }
172}
173
174impl Eval for Expression {
175 fn eval(&self, context: &mut Context) -> EvalResult<Value> {
176 log::trace!("Evaluating expression:\n{self}");
177 let result = match self {
178 Self::Literal(literal) => literal.eval(context),
179 Self::FormatString(format_string) => format_string.eval(context),
180 Self::ArrayExpression(array_expression) => array_expression.eval(context),
181 Self::TupleExpression(tuple_expression) => tuple_expression.eval(context),
182 Self::BinaryOp {
183 lhs,
184 op,
185 rhs,
186 src_ref: _,
187 } => {
188 let lhs: Value = lhs.eval(context)?;
189 let rhs: Value = rhs.eval(context)?;
190 if lhs.is_invalid() || rhs.is_invalid() {
191 return Ok(Value::None);
192 }
193
194 match Value::binary_op(lhs, rhs, op.as_str()) {
195 Err(err) => {
196 context.error(self, err)?;
197 Ok(Value::None)
198 }
199 Ok(value) => Ok(value),
200 }
201 }
202 Self::UnaryOp {
203 op,
204 rhs,
205 src_ref: _,
206 } => {
207 let value: Value = rhs.eval(context)?;
208 value.unary_op(op.as_str()).map_err(EvalError::ValueError)
209 }
210 Self::ArrayElementAccess(lhs, rhs, _) => {
211 let lhs = lhs.eval(context)?;
212 let rhs = rhs.eval(context)?;
213
214 match (lhs, rhs) {
215 (Value::Array(list), Value::Integer(index)) => {
216 let index = index as usize;
217 if index < list.len() {
218 match list.get(index) {
219 Some(value) => Ok(value.clone()),
220 None => Err(EvalError::ListIndexOutOfBounds {
221 index,
222 len: list.len(),
223 }),
224 }
225 } else {
226 context.error(
227 self,
228 EvalError::ListIndexOutOfBounds {
229 index,
230 len: list.len(),
231 },
232 )?;
233 Ok(Value::None)
234 }
235 }
236 _ => unimplemented!(),
237 }
238 }
239 Self::MethodCall(lhs, method_call, _) => method_call.eval(context, lhs),
240 Self::Call(call) => call.eval(context),
241 Self::Body(body) => {
242 let model: Model = body.eval(context)?;
243 Ok(model.into())
244 }
245 Self::QualifiedName(qualified_name) => qualified_name.eval(context),
246 Self::Marker(marker) => {
247 let model: Option<Model> = marker.eval(context)?;
248 Ok(model.map(Value::Model).unwrap_or_default())
249 }
250 Self::PropertyAccess(lhs, id, src_ref) => {
252 let value: Value = lhs.eval(context)?;
253 match value {
254 Value::Tuple(tuple) => match tuple.by_id(id) {
255 Some(value) => return Ok(value.clone()),
256 None => context.error(src_ref, EvalError::PropertyNotFound(id.clone()))?,
257 },
258 Value::Model(model) => match model.borrow().get_property(id) {
259 Some(prop) => return Ok(prop.clone()),
260 None => context.error(src_ref, EvalError::PropertyNotFound(id.clone()))?,
261 },
262 _ => {}
263 }
264
265 Ok(Value::None)
266 }
267 Self::AttributeAccess(lhs, identifier, src_ref) => {
268 let value: Value = lhs.eval(context)?;
269 let value = value.get_attribute_value(identifier);
270 if value == Value::None {
271 context.error(src_ref, AttributeError::NotFound(identifier.clone()))?;
272 }
273 Ok(value)
274 }
275 expr => todo!("{expr:?}"),
276 };
277 match &result {
278 Ok(result) => log::trace!("Evaluated expression:\n{self}\n--- into ---\n{result}"),
279 Err(_) => log::trace!("Evaluation of expression failed:\n{self}"),
280 };
281 result
282 }
283}
284
285impl Eval<Option<Model>> for Expression {
286 fn eval(&self, context: &mut Context) -> EvalResult<Option<Model>> {
287 Ok(match self.eval(context)? {
288 Value::Model(model) => Some(model),
289 _ => None,
290 })
291 }
292}