From f0c759d92a70966a2983677a328ab9d4f893638d Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 22 Aug 2023 13:19:57 -0400 Subject: [PATCH] Implement if --- src/interface.rs | 13 +---------- src/macros/logic.rs | 46 ++++++++++++++++++++++++++++++++++----- src/macros/mod.rs | 3 ++- src/value/variable_map.rs | 3 --- tests/logic.rs | 10 ++++----- 5 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index 122c397..f44e864 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -12,18 +12,7 @@ use crate::{token, tree, Result, Value, VariableMap}; /// *See the [crate doc](index.html) for more examples and explanations of the expression format.* pub fn eval(string: &str) -> Result { let mut context = VariableMap::new(); - let eval = eval_with_context(string, &mut context); - - match eval { - Ok(output) => { - if output.is_empty() { - Ok(Value::Map(context)) - } else { - Ok(output) - } - } - Err(error) => Err(error), - } + eval_with_context(string, &mut context) } /// Evaluate the given expression string with the given context. diff --git a/src/macros/logic.rs b/src/macros/logic.rs index cb9d855..55abbec 100644 --- a/src/macros/logic.rs +++ b/src/macros/logic.rs @@ -1,4 +1,4 @@ -use crate::{Error, Macro, MacroInfo, Result, Value, ValueType}; +use crate::{Error, Macro, MacroInfo, Result, Value, ValueType }; pub struct Assert; @@ -58,18 +58,54 @@ impl Macro for If { fn info(&self) -> MacroInfo<'static> { MacroInfo { identifier: "if", - description: "Evaluates the first argument. If true, it does the second argument. If false, it does the third argument", - group: "general", + description: "Evaluates the first argument. If true, it does the second argument.", + group: "logic", + inputs: vec![ + ValueType::List(vec![ + ValueType::Boolean, + ValueType::Any, + ]), + ValueType::List(vec![ + ValueType::Function, + ValueType::Any, + ])], + } + } + + fn run(&self, argument: &Value) -> Result { + let argument = argument.as_fixed_len_list(2)?; + let (condition, if_true) = (&argument[0], &argument[1]); + let condition = if let Ok(function) = condition.as_function() { + function.run()?.as_boolean()? + } else { + condition.as_boolean()? + }; + + if condition { + Ok(if_true.clone()) + } else { + Ok(Value::Empty) + } + + } +} + +pub struct IfElse; + +impl Macro for IfElse { + fn info(&self) -> MacroInfo<'static> { + MacroInfo { + identifier: "if_else", + description: "Evaluates the first argument. If true, it does the second argument. If false, it does the third argument", + group: "logic", inputs: vec![ ValueType::List(vec![ ValueType::Boolean, ValueType::Any, - ValueType::Any ]), ValueType::List(vec![ ValueType::Function, ValueType::Any, - ValueType::Any ])], } } diff --git a/src/macros/mod.rs b/src/macros/mod.rs index f5a4710..8c8bbbb 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -40,7 +40,7 @@ pub mod time; /// /// This list is used to match identifiers with macros and to provide info to /// the shell. -pub const MACRO_LIST: [&'static dyn Macro; 56] = [ +pub const MACRO_LIST: [&'static dyn Macro; 57] = [ &collections::Count, &collections::CreateTable, &collections::Get, @@ -80,6 +80,7 @@ pub const MACRO_LIST: [&'static dyn Macro; 56] = [ &gui::Plot, &gui::Gui, &logic::If, + &logic::IfElse, &logic::Loop, &network::Download, &package_management::CoprRepositories, diff --git a/src/value/variable_map.rs b/src/value/variable_map.rs index 841d475..8ba6b10 100644 --- a/src/value/variable_map.rs +++ b/src/value/variable_map.rs @@ -68,9 +68,6 @@ impl VariableMap { if argument.is_empty() { return self.call_function(function_identifier, &value); } - - let value_type = value.value_type(); - let list = Value::List(vec![value, argument.clone()]); return self.call_function(function_identifier, &list); diff --git a/tests/logic.rs b/tests/logic.rs index 1a971fb..90a178f 100644 --- a/tests/logic.rs +++ b/tests/logic.rs @@ -20,20 +20,20 @@ fn r#if() { assert_eq!(Value::Integer(1), value); let value = eval("if(false, 1)").unwrap(); - assert!(value.is_empty()); + assert_eq!(Value::Empty, value); } #[test] fn r#if_else() { - let value = eval("if(true, 1, 2)").unwrap(); + let value = eval("if_else(true, 1, 2)").unwrap(); assert_eq!(Value::Integer(1), value); - let value = eval("if(false, 1, 2)").unwrap(); + let value = eval("if_else(false, 1, 2)").unwrap(); assert_eq!(Value::Integer(2), value); - let value = eval("if(true, '1', '2')").unwrap(); + let value = eval("if_else(true, '1', '2')").unwrap(); assert_eq!(Value::Integer(1), value); - let value = eval("if(false, '1', '2')").unwrap(); + let value = eval("if_else(false, '1', '2')").unwrap(); assert_eq!(Value::Integer(2), value); }