1use gitql_ast::expression::ArithmeticExpr;
2use gitql_ast::expression::ArrayExpr;
3use gitql_ast::expression::AssignmentExpr;
4use gitql_ast::expression::BenchmarkCallExpr;
5use gitql_ast::expression::BetweenExpr;
6use gitql_ast::expression::BetweenKind;
7use gitql_ast::expression::BitwiseExpr;
8use gitql_ast::expression::BooleanExpr;
9use gitql_ast::expression::CallExpr;
10use gitql_ast::expression::CaseExpr;
11use gitql_ast::expression::CastExpr;
12use gitql_ast::expression::ColumnExpr;
13use gitql_ast::expression::ComparisonExpr;
14use gitql_ast::expression::ContainedByExpr;
15use gitql_ast::expression::ContainsExpr;
16use gitql_ast::expression::Expr;
17use gitql_ast::expression::ExprKind::*;
18use gitql_ast::expression::GlobExpr;
19use gitql_ast::expression::GlobalVariableExpr;
20use gitql_ast::expression::GroupComparisonExpr;
21use gitql_ast::expression::InExpr;
22use gitql_ast::expression::IndexExpr;
23use gitql_ast::expression::IntervalExpr;
24use gitql_ast::expression::IsNullExpr;
25use gitql_ast::expression::LikeExpr;
26use gitql_ast::expression::LogicalExpr;
27use gitql_ast::expression::MemberAccessExpr;
28use gitql_ast::expression::Number;
29use gitql_ast::expression::NumberExpr;
30use gitql_ast::expression::RegexExpr;
31use gitql_ast::expression::RowExpr;
32use gitql_ast::expression::SliceExpr;
33use gitql_ast::expression::StringExpr;
34use gitql_ast::expression::SymbolExpr;
35use gitql_ast::expression::UnaryExpr;
36use gitql_ast::operator::ArithmeticOperator;
37use gitql_ast::operator::BinaryBitwiseOperator;
38use gitql_ast::operator::BinaryLogicalOperator;
39use gitql_ast::operator::ComparisonOperator;
40use gitql_ast::operator::PrefixUnaryOperator;
41use gitql_core::environment::Environment;
42use gitql_core::values::array::ArrayValue;
43use gitql_core::values::boolean::BoolValue;
44use gitql_core::values::composite::CompositeValue;
45use gitql_core::values::float::FloatValue;
46use gitql_core::values::integer::IntValue;
47use gitql_core::values::interval::IntervalValue;
48use gitql_core::values::null::NullValue;
49use gitql_core::values::row::RowValue;
50use gitql_core::values::text::TextValue;
51use gitql_core::values::Value;
52
53use std::cmp::Ordering;
54use std::string::String;
55
56#[allow(clippy::borrowed_box)]
57pub fn evaluate_expression(
58 env: &mut Environment,
59 expression: &Box<dyn Expr>,
60 titles: &[String],
61 object: &Vec<Box<dyn Value>>,
62) -> Result<Box<dyn Value>, String> {
63 match expression.kind() {
64 Assignment => {
65 let expr = expression
66 .as_any()
67 .downcast_ref::<AssignmentExpr>()
68 .unwrap();
69 evaluate_assignment(env, expr, titles, object)
70 }
71 String => {
72 let expr = expression.as_any().downcast_ref::<StringExpr>().unwrap();
73 evaluate_string(expr)
74 }
75 Symbol => {
76 let expr = expression.as_any().downcast_ref::<SymbolExpr>().unwrap();
77 evaluate_symbol(expr, titles, object)
78 }
79 Array => {
80 let expr = expression.as_any().downcast_ref::<ArrayExpr>().unwrap();
81 evaluate_array(env, expr, titles, object)
82 }
83 GlobalVariable => {
84 let expr = expression
85 .as_any()
86 .downcast_ref::<GlobalVariableExpr>()
87 .unwrap();
88 evaluate_global_variable(env, expr)
89 }
90 Number => {
91 let expr = expression.as_any().downcast_ref::<NumberExpr>().unwrap();
92 evaluate_number(expr)
93 }
94 Boolean => {
95 let expr = expression.as_any().downcast_ref::<BooleanExpr>().unwrap();
96 evaluate_boolean(expr)
97 }
98 Interval => {
99 let expr = expression.as_any().downcast_ref::<IntervalExpr>().unwrap();
100 evaluate_interval(expr)
101 }
102 PrefixUnary => {
103 let expr = expression.as_any().downcast_ref::<UnaryExpr>().unwrap();
104 evaluate_prefix_unary(env, expr, titles, object)
105 }
106 Index => {
107 let expr = expression.as_any().downcast_ref::<IndexExpr>().unwrap();
108 evaluate_collection_index(env, expr, titles, object)
109 }
110 Slice => {
111 let expr = expression.as_any().downcast_ref::<SliceExpr>().unwrap();
112 evaluate_collection_slice(env, expr, titles, object)
113 }
114 Arithmetic => {
115 let expr = expression
116 .as_any()
117 .downcast_ref::<ArithmeticExpr>()
118 .unwrap();
119 evaluate_arithmetic(env, expr, titles, object)
120 }
121 Comparison => {
122 let expr = expression
123 .as_any()
124 .downcast_ref::<ComparisonExpr>()
125 .unwrap();
126 evaluate_comparison(env, expr, titles, object)
127 }
128 GroupComparison => {
129 let expr = expression
130 .as_any()
131 .downcast_ref::<GroupComparisonExpr>()
132 .unwrap();
133 evaluate_group_comparison(env, expr, titles, object)
134 }
135 Contains => {
136 let expr = expression.as_any().downcast_ref::<ContainsExpr>().unwrap();
137 evaluate_contains(env, expr, titles, object)
138 }
139 ContainedBy => {
140 let expr = expression
141 .as_any()
142 .downcast_ref::<ContainedByExpr>()
143 .unwrap();
144 evaluate_contained_by(env, expr, titles, object)
145 }
146 Like => {
147 let expr = expression.as_any().downcast_ref::<LikeExpr>().unwrap();
148 evaluate_like(env, expr, titles, object)
149 }
150 Regex => {
151 let expr = expression.as_any().downcast_ref::<RegexExpr>().unwrap();
152 evaluate_regex(env, expr, titles, object)
153 }
154 Glob => {
155 let expr = expression.as_any().downcast_ref::<GlobExpr>().unwrap();
156 evaluate_glob(env, expr, titles, object)
157 }
158 Logical => {
159 let expr = expression.as_any().downcast_ref::<LogicalExpr>().unwrap();
160 evaluate_logical(env, expr, titles, object)
161 }
162 Bitwise => {
163 let expr = expression.as_any().downcast_ref::<BitwiseExpr>().unwrap();
164 evaluate_bitwise(env, expr, titles, object)
165 }
166 Call => {
167 let expr = expression.as_any().downcast_ref::<CallExpr>().unwrap();
168 evaluate_call(env, expr, titles, object)
169 }
170 BenchmarkCall => {
171 let expr = expression
172 .as_any()
173 .downcast_ref::<BenchmarkCallExpr>()
174 .unwrap();
175 evaluate_benchmark_call(env, expr, titles, object)
176 }
177 Between => {
178 let expr = expression.as_any().downcast_ref::<BetweenExpr>().unwrap();
179 evaluate_between(env, expr, titles, object)
180 }
181 Case => {
182 let expr = expression.as_any().downcast_ref::<CaseExpr>().unwrap();
183 evaluate_case(env, expr, titles, object)
184 }
185 In => {
186 let expr = expression.as_any().downcast_ref::<InExpr>().unwrap();
187 evaluate_in(env, expr, titles, object)
188 }
189 IsNull => {
190 let expr = expression.as_any().downcast_ref::<IsNullExpr>().unwrap();
191 evaluate_is_null(env, expr, titles, object)
192 }
193 Cast => {
194 let expr = expression.as_any().downcast_ref::<CastExpr>().unwrap();
195 evaluate_cast(env, expr, titles, object)
196 }
197 Column => {
198 let expr = expression.as_any().downcast_ref::<ColumnExpr>().unwrap();
199 evaluate_column(env, expr, titles, object)
200 }
201 Row => {
202 let expr = expression.as_any().downcast_ref::<RowExpr>().unwrap();
203 evaluate_row(env, expr, titles, object)
204 }
205 MemberAccess => {
206 let expr = expression
207 .as_any()
208 .downcast_ref::<MemberAccessExpr>()
209 .unwrap();
210 evaluate_member_access(env, expr, titles, object)
211 }
212 Null => Ok(Box::new(NullValue)),
213 }
214}
215
216fn evaluate_assignment(
217 env: &mut Environment,
218 expr: &AssignmentExpr,
219 titles: &[String],
220 object: &Vec<Box<dyn Value>>,
221) -> Result<Box<dyn Value>, String> {
222 let value = evaluate_expression(env, &expr.value, titles, object)?;
223 env.globals.insert(expr.symbol.to_string(), value.clone());
224 Ok(value)
225}
226
227fn evaluate_string(expr: &StringExpr) -> Result<Box<dyn Value>, String> {
228 Ok(Box::new(TextValue::new(expr.value.to_owned())))
229}
230
231fn evaluate_symbol(
232 expr: &SymbolExpr,
233 titles: &[String],
234 object: &[Box<dyn Value>],
235) -> Result<Box<dyn Value>, String> {
236 for (index, title) in titles.iter().enumerate() {
237 if expr.value.eq(title) {
238 return Ok(object[index].clone());
239 }
240 }
241 Err(format!("Invalid column name `{}`", &expr.value))
242}
243
244fn evaluate_array(
245 env: &mut Environment,
246 expr: &ArrayExpr,
247 titles: &[String],
248 object: &Vec<Box<dyn Value>>,
249) -> Result<Box<dyn Value>, String> {
250 let mut values: Vec<Box<dyn Value>> = Vec::with_capacity(expr.values.len());
251 for value in &expr.values {
252 values.push(evaluate_expression(env, value, titles, object)?);
253 }
254 Ok(Box::new(ArrayValue::new(values, expr.element_type.clone())))
255}
256
257fn evaluate_global_variable(
258 env: &mut Environment,
259 expr: &GlobalVariableExpr,
260) -> Result<Box<dyn Value>, String> {
261 let name = &expr.name;
262 if env.globals.contains_key(name) {
263 return Ok(env.globals[name].clone());
264 }
265
266 Err(format!(
267 "The value of `{name}` may be not exists or calculated yet",
268 ))
269}
270
271fn evaluate_number(expr: &NumberExpr) -> Result<Box<dyn Value>, String> {
272 Ok(match expr.value {
273 Number::Int(integer) => Box::new(IntValue::new(integer)),
274 Number::Float(float) => Box::new(FloatValue::new(float)),
275 })
276}
277
278fn evaluate_boolean(expr: &BooleanExpr) -> Result<Box<dyn Value>, String> {
279 Ok(Box::new(BoolValue::new(expr.is_true)))
280}
281
282fn evaluate_interval(expr: &IntervalExpr) -> Result<Box<dyn Value>, String> {
283 Ok(Box::new(IntervalValue::new(expr.interval.clone())))
284}
285
286fn evaluate_collection_index(
287 env: &mut Environment,
288 expr: &IndexExpr,
289 titles: &[String],
290 object: &Vec<Box<dyn Value>>,
291) -> Result<Box<dyn Value>, String> {
292 let array = evaluate_expression(env, &expr.collection, titles, object)?;
293 let index = evaluate_expression(env, &expr.index, titles, object)?;
294 array.index_op(&index)
295}
296
297fn evaluate_collection_slice(
298 env: &mut Environment,
299 expr: &SliceExpr,
300 titles: &[String],
301 object: &Vec<Box<dyn Value>>,
302) -> Result<Box<dyn Value>, String> {
303 let array = evaluate_expression(env, &expr.collection, titles, object)?;
304
305 let start = if let Some(start_expr) = &expr.start {
306 Some(evaluate_expression(env, start_expr, titles, object)?)
307 } else {
308 None
309 };
310
311 let end = if let Some(end_expr) = &expr.end {
312 Some(evaluate_expression(env, end_expr, titles, object)?)
313 } else {
314 None
315 };
316
317 array.slice_op(&start, &end)
318}
319
320fn evaluate_prefix_unary(
321 env: &mut Environment,
322 expr: &UnaryExpr,
323 titles: &[String],
324 object: &Vec<Box<dyn Value>>,
325) -> Result<Box<dyn Value>, String> {
326 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
327 match expr.operator {
328 PrefixUnaryOperator::Negative => rhs.neg_op(),
329 PrefixUnaryOperator::Bang => rhs.bang_op(),
330 PrefixUnaryOperator::Not => rhs.not_op(),
331 }
332}
333
334fn evaluate_arithmetic(
335 env: &mut Environment,
336 expr: &ArithmeticExpr,
337 titles: &[String],
338 object: &Vec<Box<dyn Value>>,
339) -> Result<Box<dyn Value>, String> {
340 let lhs = evaluate_expression(env, &expr.left, titles, object)?;
341 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
342 match expr.operator {
343 ArithmeticOperator::Plus => lhs.add_op(&rhs),
344 ArithmeticOperator::Minus => lhs.sub_op(&rhs),
345 ArithmeticOperator::Star => lhs.mul_op(&rhs),
346 ArithmeticOperator::Slash => lhs.div_op(&rhs),
347 ArithmeticOperator::Modulus => lhs.rem_op(&rhs),
348 ArithmeticOperator::Exponentiation => lhs.caret_op(&rhs),
349 }
350}
351
352fn evaluate_comparison(
353 env: &mut Environment,
354 expr: &ComparisonExpr,
355 titles: &[String],
356 object: &Vec<Box<dyn Value>>,
357) -> Result<Box<dyn Value>, String> {
358 let lhs = evaluate_expression(env, &expr.left, titles, object)?;
359 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
360 match expr.operator {
361 ComparisonOperator::Greater => lhs.gt_op(&rhs),
362 ComparisonOperator::GreaterEqual => lhs.gte_op(&rhs),
363 ComparisonOperator::Less => lhs.lt_op(&rhs),
364 ComparisonOperator::LessEqual => lhs.lte_op(&rhs),
365 ComparisonOperator::Equal => lhs.eq_op(&rhs),
366 ComparisonOperator::NotEqual => lhs.bang_eq_op(&rhs),
367 ComparisonOperator::NullSafeEqual => lhs.null_safe_eq_op(&rhs),
368 }
369}
370
371fn evaluate_group_comparison(
372 env: &mut Environment,
373 expr: &GroupComparisonExpr,
374 titles: &[String],
375 object: &Vec<Box<dyn Value>>,
376) -> Result<Box<dyn Value>, String> {
377 let lhs = evaluate_expression(env, &expr.left, titles, object)?;
378 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
379 match expr.comparison_operator {
380 ComparisonOperator::Greater => lhs.group_gt_op(&rhs, &expr.group_operator),
381 ComparisonOperator::GreaterEqual => lhs.group_gte_op(&rhs, &expr.group_operator),
382 ComparisonOperator::Less => lhs.group_lt_op(&rhs, &expr.group_operator),
383 ComparisonOperator::LessEqual => lhs.group_lte_op(&rhs, &expr.group_operator),
384 ComparisonOperator::Equal => lhs.group_eq_op(&rhs, &expr.group_operator),
385 ComparisonOperator::NotEqual => lhs.group_bang_eq_op(&rhs, &expr.group_operator),
386 ComparisonOperator::NullSafeEqual => lhs.group_null_safe_eq_op(&rhs, &expr.group_operator),
387 }
388}
389
390fn evaluate_contains(
391 env: &mut Environment,
392 expr: &ContainsExpr,
393 titles: &[String],
394 object: &Vec<Box<dyn Value>>,
395) -> Result<Box<dyn Value>, String> {
396 let lhs = evaluate_expression(env, &expr.left, titles, object)?;
397 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
398 lhs.contains_op(&rhs)
399}
400
401fn evaluate_contained_by(
402 env: &mut Environment,
403 expr: &ContainedByExpr,
404 titles: &[String],
405 object: &Vec<Box<dyn Value>>,
406) -> Result<Box<dyn Value>, String> {
407 let lhs = evaluate_expression(env, &expr.left, titles, object)?;
408 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
409 rhs.contains_op(&lhs)
410}
411
412fn evaluate_like(
413 env: &mut Environment,
414 expr: &LikeExpr,
415 titles: &[String],
416 object: &Vec<Box<dyn Value>>,
417) -> Result<Box<dyn Value>, String> {
418 let input = evaluate_expression(env, &expr.input, titles, object)?;
419 let pattern = evaluate_expression(env, &expr.pattern, titles, object)?;
420 input.like_op(&pattern)
421}
422
423fn evaluate_regex(
424 env: &mut Environment,
425 expr: &RegexExpr,
426 titles: &[String],
427 object: &Vec<Box<dyn Value>>,
428) -> Result<Box<dyn Value>, String> {
429 let input = evaluate_expression(env, &expr.input, titles, object)?;
430 let pattern = evaluate_expression(env, &expr.pattern, titles, object)?;
431 input.regexp_op(&pattern)
432}
433
434fn evaluate_glob(
435 env: &mut Environment,
436 expr: &GlobExpr,
437 titles: &[String],
438 object: &Vec<Box<dyn Value>>,
439) -> Result<Box<dyn Value>, String> {
440 let input = evaluate_expression(env, &expr.input, titles, object)?;
441 let pattern = evaluate_expression(env, &expr.pattern, titles, object)?;
442 input.glob_op(&pattern)
443}
444
445fn evaluate_logical(
446 env: &mut Environment,
447 expr: &LogicalExpr,
448 titles: &[String],
449 object: &Vec<Box<dyn Value>>,
450) -> Result<Box<dyn Value>, String> {
451 let lhs = evaluate_expression(env, &expr.left, titles, object)?;
452 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
453 match expr.operator {
454 BinaryLogicalOperator::And => lhs.logical_and_op(&rhs),
455 BinaryLogicalOperator::Or => lhs.logical_or_op(&rhs),
456 BinaryLogicalOperator::Xor => lhs.logical_xor_op(&rhs),
457 }
458}
459
460fn evaluate_bitwise(
461 env: &mut Environment,
462 expr: &BitwiseExpr,
463 titles: &[String],
464 object: &Vec<Box<dyn Value>>,
465) -> Result<Box<dyn Value>, String> {
466 let lhs = evaluate_expression(env, &expr.left, titles, object)?;
467 let rhs = evaluate_expression(env, &expr.right, titles, object)?;
468 match expr.operator {
469 BinaryBitwiseOperator::Or => lhs.or_op(&rhs),
470 BinaryBitwiseOperator::And => lhs.and_op(&rhs),
471 BinaryBitwiseOperator::Xor => lhs.xor_op(&rhs),
472 BinaryBitwiseOperator::RightShift => lhs.shr_op(&rhs),
473 BinaryBitwiseOperator::LeftShift => lhs.shl_op(&rhs),
474 }
475}
476
477fn evaluate_call(
478 env: &mut Environment,
479 expr: &CallExpr,
480 titles: &[String],
481 object: &Vec<Box<dyn Value>>,
482) -> Result<Box<dyn Value>, String> {
483 let function_name = expr.function_name.as_str();
484 let mut arguments = Vec::with_capacity(expr.arguments.len());
485 for arg in expr.arguments.iter() {
486 arguments.push(evaluate_expression(env, arg, titles, object)?);
487 }
488 let function = env.std_function(function_name).unwrap();
489 Ok(function(&arguments))
490}
491
492fn evaluate_benchmark_call(
493 env: &mut Environment,
494 expr: &BenchmarkCallExpr,
495 titles: &[String],
496 object: &Vec<Box<dyn Value>>,
497) -> Result<Box<dyn Value>, String> {
498 let number_of_execution = evaluate_expression(env, &expr.count, titles, object)?;
499 if let Some(number) = number_of_execution.as_any().downcast_ref::<IntValue>() {
500 for _ in 0..number.value {
501 evaluate_expression(env, &expr.expression, titles, object)?;
502 }
503 }
504 Ok(Box::new(IntValue::new_zero()))
505}
506
507fn evaluate_between(
508 env: &mut Environment,
509 expr: &BetweenExpr,
510 titles: &[String],
511 object: &Vec<Box<dyn Value>>,
512) -> Result<Box<dyn Value>, String> {
513 let value = evaluate_expression(env, &expr.value, titles, object)?;
514 let range_start = evaluate_expression(env, &expr.range_start, titles, object)?;
515 let range_end = evaluate_expression(env, &expr.range_end, titles, object)?;
516 let comparing_result = match expr.kind {
517 BetweenKind::Symmetric => {
518 let (start, end) = if let Some(order) = range_start.compare(&range_end) {
519 if Ordering::is_gt(order) {
520 (range_end, range_start)
521 } else {
522 (range_start, range_end)
523 }
524 } else {
525 (range_start, range_end)
526 };
527 value.compare(&start).unwrap().is_ge() && value.compare(&end).unwrap().is_le()
528 }
529 BetweenKind::Asymmetric => {
530 value.compare(&range_start).unwrap().is_ge()
531 && value.compare(&range_end).unwrap().is_le()
532 }
533 };
534 Ok(Box::new(BoolValue::new(comparing_result)))
535}
536
537fn evaluate_case(
538 env: &mut Environment,
539 expr: &CaseExpr,
540 titles: &[String],
541 object: &Vec<Box<dyn Value>>,
542) -> Result<Box<dyn Value>, String> {
543 let conditions = &expr.conditions;
544 let values = &expr.values;
545
546 for i in 0..conditions.len() {
547 let condition = evaluate_expression(env, &conditions[i], titles, object)?;
548 if let Some(bool_value) = condition.as_any().downcast_ref::<BoolValue>() {
549 if bool_value.value {
550 return evaluate_expression(env, &values[i], titles, object);
551 }
552 }
553 }
554
555 match &expr.default_value {
556 Some(default_value) => evaluate_expression(env, default_value, titles, object),
557 _ => Err("Invalid case statement".to_owned()),
558 }
559}
560
561fn evaluate_in(
562 env: &mut Environment,
563 expr: &InExpr,
564 titles: &[String],
565 object: &Vec<Box<dyn Value>>,
566) -> Result<Box<dyn Value>, String> {
567 let argument = evaluate_expression(env, &expr.argument, titles, object)?;
568 for value_expr in &expr.values {
569 let value = evaluate_expression(env, value_expr, titles, object)?;
570 if argument.equals(&value) {
571 return Ok(Box::new(BoolValue::new(!expr.has_not_keyword)));
572 }
573 }
574 Ok(Box::new(BoolValue::new(expr.has_not_keyword)))
575}
576
577fn evaluate_is_null(
578 env: &mut Environment,
579 expr: &IsNullExpr,
580 titles: &[String],
581 object: &Vec<Box<dyn Value>>,
582) -> Result<Box<dyn Value>, String> {
583 let argument = evaluate_expression(env, &expr.argument, titles, object)?;
584 let is_null = argument.as_any().downcast_ref::<NullValue>().is_some();
585 let result = if expr.has_not { !is_null } else { is_null };
586 Ok(Box::new(BoolValue::new(result)))
587}
588
589fn evaluate_cast(
590 env: &mut Environment,
591 expr: &CastExpr,
592 titles: &[String],
593 object: &Vec<Box<dyn Value>>,
594) -> Result<Box<dyn Value>, String> {
595 let value = evaluate_expression(env, &expr.value, titles, object)?;
596 value.cast_op(&expr.result_type)
597}
598
599fn evaluate_column(
600 env: &mut Environment,
601 expr: &ColumnExpr,
602 titles: &[String],
603 object: &Vec<Box<dyn Value>>,
604) -> Result<Box<dyn Value>, String> {
605 let value = evaluate_expression(env, &expr.expr, titles, object)?;
606 Ok(value)
607}
608
609fn evaluate_row(
610 env: &mut Environment,
611 expr: &RowExpr,
612 titles: &[String],
613 object: &Vec<Box<dyn Value>>,
614) -> Result<Box<dyn Value>, String> {
615 let mut values = Vec::with_capacity(expr.exprs.len());
616 for column in expr.exprs.iter() {
617 values.push(evaluate_expression(env, column, titles, object)?);
618 }
619 Ok(Box::new(RowValue::new(values, expr.row_type.to_owned())))
620}
621
622fn evaluate_member_access(
623 env: &mut Environment,
624 expr: &MemberAccessExpr,
625 titles: &[String],
626 object: &Vec<Box<dyn Value>>,
627) -> Result<Box<dyn Value>, String> {
628 let value = evaluate_expression(env, &expr.composite, titles, object)?;
629 if let Some(composite_value) = value.as_any().downcast_ref::<CompositeValue>() {
630 let member_name = &expr.member_name;
631 return Ok(composite_value.members.get(member_name).unwrap().clone());
632 }
633 Err("Invalid value for Member access expression".to_owned())
634}