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