diff --git a/golem-worker-service-base/src/evaluator/mod.rs b/golem-worker-service-base/src/evaluator/mod.rs index 844620a58f..ce120f936f 100644 --- a/golem-worker-service-base/src/evaluator/mod.rs +++ b/golem-worker-service-base/src/evaluator/mod.rs @@ -8,6 +8,7 @@ use getter::Getter; use path::Path; use crate::expression::{Expr, InnerNumber}; +use crate::merge::Merge; use crate::tokeniser::tokenizer::{MultiCharTokens, Token, Tokenizer}; @@ -173,7 +174,36 @@ impl Evaluator for Expr { } } - Expr::Let(_, _) | Expr::Multiple(_) => todo!(), + Expr::Let(str, expr) => { + let value = go(expr, input)?; + let typ = AnalysedType::from(&value); + + let result = TypeAnnotatedValue::Record { + value: vec![(str.to_string(), value)], + typ: vec![(str.to_string(), typ)], + }; + + input.merge(&result); + + Ok(result) + } + + // TODO; + Expr::Multiple(multiple) => { + let mut result: Vec = vec![]; + + for expr in multiple { + match go(expr, input) { + Ok(value) => { + input.merge(&value); + result.push(value); + } + Err(result) => return Err(result), + } + } + + Ok(result.last().unwrap().clone()) + } Expr::Sequence(exprs) => { let mut result: Vec = vec![]; @@ -1301,6 +1331,30 @@ mod tests { assert_eq!(result, expected); } + #[test] + fn test_evaluation_with_multiple_lines() { + let program = r" + let x = { a : 1 }; + let y = { b : 2 }; + let z = x.a > y.b; + z + "; + + let expr = expression::from_string(format!("${{{}}}", program)).unwrap(); + + // We don't need any information any request to evaluate the above program + let empty_input = &TypeAnnotatedValue::Record { + value: vec![], + typ: vec![], + }; + + let result = expr.evaluate(empty_input); + + let expected = Ok(TypeAnnotatedValue::Bool(false)); + + assert_eq!(result, expected); + } + mod test_utils { use crate::api_definition::http::{AllPathPatterns, PathPattern}; use crate::evaluator::Evaluator; diff --git a/golem-worker-service-base/src/parser/expr/expr_parser.rs b/golem-worker-service-base/src/parser/expr/expr_parser.rs index 9cee0c59a1..2bb1cbc48b 100644 --- a/golem-worker-service-base/src/parser/expr/expr_parser.rs +++ b/golem-worker-service-base/src/parser/expr/expr_parser.rs @@ -1140,4 +1140,52 @@ mod tests { assert_eq!(result, expected); } + + #[test] + fn test_let_binding() { + let expression_parser = ExprParser {}; + + let result = expression_parser.parse("${let x = 1;}").unwrap(); + + let expected = Expr::Let("x".to_string(), Box::new(Expr::unsigned_integer(1))); + + assert_eq!(result, expected); + } + + #[test] + fn multi_line_expressions() { + let expression_parser = ExprParser {}; + + let program = r" + let x = 1; + let y = x > 1; + let z = y < x; + x + "; + + let result = expression_parser + .parse(format!("${{{}}}", program).as_str()) + .unwrap(); + + let expected = Expr::Multiple(vec![ + Expr::Let("x".to_string(), Box::new(Expr::unsigned_integer(1))), + Expr::Let( + "y".to_string(), + Box::new(Expr::GreaterThan( + Box::new(Expr::Variable("x".to_string())), + Box::new(Expr::unsigned_integer(1)), + )), + ), + Expr::Let( + "z".to_string(), + Box::new(Expr::LessThan( + Box::new(Expr::Variable("y".to_string())), + Box::new(Expr::Variable("x".to_string())), + )), + ), + Expr::Variable("x".to_string()), + ]); + + assert_eq!(result, expected); + } }