1use crate::{eval::*, model::*};
5
6impl Eval for RangeFirst {
7 fn eval(&self, context: &mut EvalContext) -> 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 EvalContext) -> 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 EvalContext) -> EvalResult<Value> {
48 Ok(
49 match (self.first.eval(context)?, self.last.eval(context)?) {
50 (Value::Integer(first), Value::Integer(last)) => Value::Array(Array::from_values(
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 EvalContext) -> 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::from_values(value_list, common_type)) * self.unit
75 {
76 Ok(value) => Ok(value),
77 Err(err) => {
78 context.error(self, err)?;
79 Ok(Value::None)
80 }
81 }
82 }
83 None => {
84 context.error(
85 self,
86 EvalError::ArrayElementsDifferentTypes(value_list.types()),
87 )?;
88 Ok(Value::None)
89 }
90 }
91 }
92 }
93 }
94}
95
96impl Eval<Option<Symbol>> for QualifiedName {
97 fn eval(&self, context: &mut EvalContext) -> EvalResult<Option<Symbol>> {
98 match context.lookup(self) {
99 Ok(symbol) => Ok(Some(symbol.clone())),
100 Err(error) => {
101 context.error(self, error)?;
102 Ok(None)
103 }
104 }
105 }
106}
107
108impl Eval for QualifiedName {
109 fn eval(&self, context: &mut EvalContext) -> EvalResult<Value> {
110 context.lookup(self)?.with_def(|def| match def {
111 SymbolDefinition::Constant(.., value) | SymbolDefinition::Argument(_, value) => {
112 Ok(value.clone())
113 }
114 SymbolDefinition::ConstExpression(.., expr) => expr.eval(context),
115 SymbolDefinition::SourceFile(_) => Ok(Value::None),
116
117 SymbolDefinition::Module(ns) => {
118 context.error(self, EvalError::UnexpectedNested("mod", ns.id.clone()))?;
119 Ok(Value::None)
120 }
121 SymbolDefinition::Workbench(w) => {
122 context.error(
123 self,
124 EvalError::UnexpectedNested(w.kind.as_str(), w.id.clone()),
125 )?;
126 Ok(Value::None)
127 }
128 SymbolDefinition::Function(f) => {
129 context.error(self, EvalError::UnexpectedNested("function", f.id.clone()))?;
130 Ok(Value::None)
131 }
132 SymbolDefinition::Builtin(bm) => {
133 context.error(self, EvalError::UnexpectedNested("builtin", bm.id.clone()))?;
134 Ok(Value::None)
135 }
136 SymbolDefinition::Alias(_, id, _) => {
137 unreachable!(
139 "Unexpected alias {id} in value expression at {}",
140 self.src_ref()
141 )
142 }
143 SymbolDefinition::UseAll(_, name) => {
144 unreachable!("Unexpected use {name} in value expression")
145 }
146 #[cfg(test)]
147 SymbolDefinition::Tester(..) => {
148 unreachable!()
149 }
150 })
151 }
152}
153
154impl Expression {
155 pub fn eval_with_attribute_list(
160 &self,
161 attribute_list: &AttributeList,
162 context: &mut EvalContext,
163 ) -> EvalResult<Value> {
164 let value = self.eval(context)?;
165 match value {
166 Value::Model(model) => {
167 let attributes = attribute_list.eval(context)?;
168 model.borrow_mut().attributes = attributes.clone();
169 Ok(Value::Model(model))
170 }
171 Value::None => Ok(Value::None),
172 _ => {
173 if !attribute_list.is_empty() {
174 context.error(
175 attribute_list,
176 AttributeError::CannotAssignAttribute(self.to_string()),
177 )?;
178 }
179 Ok(value)
180 }
181 }
182 }
183}
184
185impl Eval for Expression {
186 fn eval(&self, context: &mut EvalContext) -> EvalResult<Value> {
187 log::trace!("Evaluating expression:\n{self}");
188 let result = match self {
189 Self::Literal(literal) => literal.eval(context),
190 Self::FormatString(format_string) => format_string.eval(context),
191 Self::ArrayExpression(array_expression) => array_expression.eval(context),
192 Self::TupleExpression(tuple_expression) => tuple_expression.eval(context),
193 Self::BinaryOp {
194 lhs,
195 op,
196 rhs,
197 src_ref: _,
198 } => {
199 let lhs: Value = lhs.eval(context)?;
200 let rhs: Value = rhs.eval(context)?;
201 if lhs.is_invalid() || rhs.is_invalid() {
202 return Ok(Value::None);
203 }
204
205 match Value::binary_op(lhs, rhs, op.as_str()) {
206 Err(err) => {
207 context.error(self, err)?;
208 Ok(Value::None)
209 }
210 Ok(value) => Ok(value),
211 }
212 }
213 Self::UnaryOp {
214 op,
215 rhs,
216 src_ref: _,
217 } => {
218 let value: Value = rhs.eval(context)?;
219 value.unary_op(op.as_str()).map_err(EvalError::ValueError)
220 }
221 Self::ArrayElementAccess(lhs, rhs, _) => {
222 let lhs = lhs.eval(context)?;
223 let rhs = rhs.eval(context)?;
224
225 match (lhs, rhs) {
226 (Value::Array(list), Value::Integer(index)) => {
227 let index = index as usize;
228 if index < list.len() {
229 match list.get(index) {
230 Some(value) => Ok(value.clone()),
231 None => Err(EvalError::ListIndexOutOfBounds {
232 index,
233 len: list.len(),
234 }),
235 }
236 } else {
237 context.error(
238 self,
239 EvalError::ListIndexOutOfBounds {
240 index,
241 len: list.len(),
242 },
243 )?;
244 Ok(Value::None)
245 }
246 }
247 _ => unimplemented!(),
248 }
249 }
250 Self::MethodCall(lhs, method_call, _) => method_call.eval(context, lhs),
251 Self::Call(call) => call.eval(context),
252 Self::Body(body) => {
253 if let Some(model) = body.eval(context)? {
254 Ok(model.into())
255 } else {
256 Ok(Value::None)
257 }
258 }
259 Self::QualifiedName(qualified_name) => qualified_name.eval(context),
260 Self::Marker(marker) => {
261 let model: Option<Model> = marker.eval(context)?;
262 Ok(model.map(Value::Model).unwrap_or_default())
263 }
264 Self::PropertyAccess(lhs, id, src_ref) => {
266 let value: Value = lhs.eval(context)?;
267 match value {
268 Value::Tuple(tuple) => match tuple.by_id(id) {
269 Some(value) => return Ok(value.clone()),
270 None => context.error(src_ref, EvalError::PropertyNotFound(id.clone()))?,
271 },
272 Value::Model(model) => match model.borrow().get_property(id) {
273 Some(prop) => return Ok(prop.clone()),
274 None => context.error(src_ref, EvalError::PropertyNotFound(id.clone()))?,
275 },
276 _ => {}
277 }
278
279 Ok(Value::None)
280 }
281 Self::AttributeAccess(lhs, identifier, src_ref) => {
282 let value: Value = lhs.eval(context)?;
283 let value = value.get_attribute_value(identifier);
284 if value == Value::None {
285 context.error(src_ref, AttributeError::NotFound(identifier.clone()))?;
286 }
287 Ok(value)
288 }
289 expr => todo!("{expr:?}"),
290 };
291 match result {
292 Ok(value) => {
293 log::trace!("Evaluated expression:\n{self:?}\n--- into ---\n{value:?}");
294 Ok(value)
295 }
296 Err(err) => {
297 context.error(self, err)?;
298 Ok(Value::None)
299 }
300 }
301 }
302}
303
304impl Eval<Option<Model>> for Expression {
305 fn eval(&self, context: &mut EvalContext) -> EvalResult<Option<Model>> {
306 Ok(match self.eval(context)? {
307 Value::Model(model) => Some(model),
308 _ => None,
309 })
310 }
311}