Implement if

This commit is contained in:
Jeff 2023-08-22 13:19:57 -04:00
parent f15c8ef2ef
commit f0c759d92a
5 changed files with 49 additions and 26 deletions

View File

@ -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.* /// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
pub fn eval(string: &str) -> Result<Value> { pub fn eval(string: &str) -> Result<Value> {
let mut context = VariableMap::new(); let mut context = VariableMap::new();
let eval = eval_with_context(string, &mut context); 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),
}
} }
/// Evaluate the given expression string with the given context. /// Evaluate the given expression string with the given context.

View File

@ -58,18 +58,54 @@ impl Macro for If {
fn info(&self) -> MacroInfo<'static> { fn info(&self) -> MacroInfo<'static> {
MacroInfo { MacroInfo {
identifier: "if", identifier: "if",
description: "Evaluates the first argument. If true, it does the second argument. If false, it does the third argument", description: "Evaluates the first argument. If true, it does the second argument.",
group: "general", group: "logic",
inputs: vec![
ValueType::List(vec![
ValueType::Boolean,
ValueType::Any,
]),
ValueType::List(vec![
ValueType::Function,
ValueType::Any,
])],
}
}
fn run(&self, argument: &Value) -> Result<Value> {
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![ inputs: vec![
ValueType::List(vec![ ValueType::List(vec![
ValueType::Boolean, ValueType::Boolean,
ValueType::Any, ValueType::Any,
ValueType::Any
]), ]),
ValueType::List(vec![ ValueType::List(vec![
ValueType::Function, ValueType::Function,
ValueType::Any, ValueType::Any,
ValueType::Any
])], ])],
} }
} }

View File

@ -40,7 +40,7 @@ pub mod time;
/// ///
/// This list is used to match identifiers with macros and to provide info to /// This list is used to match identifiers with macros and to provide info to
/// the shell. /// the shell.
pub const MACRO_LIST: [&'static dyn Macro; 56] = [ pub const MACRO_LIST: [&'static dyn Macro; 57] = [
&collections::Count, &collections::Count,
&collections::CreateTable, &collections::CreateTable,
&collections::Get, &collections::Get,
@ -80,6 +80,7 @@ pub const MACRO_LIST: [&'static dyn Macro; 56] = [
&gui::Plot, &gui::Plot,
&gui::Gui, &gui::Gui,
&logic::If, &logic::If,
&logic::IfElse,
&logic::Loop, &logic::Loop,
&network::Download, &network::Download,
&package_management::CoprRepositories, &package_management::CoprRepositories,

View File

@ -68,9 +68,6 @@ impl VariableMap {
if argument.is_empty() { if argument.is_empty() {
return self.call_function(function_identifier, &value); return self.call_function(function_identifier, &value);
} }
let value_type = value.value_type();
let list = Value::List(vec![value, argument.clone()]); let list = Value::List(vec![value, argument.clone()]);
return self.call_function(function_identifier, &list); return self.call_function(function_identifier, &list);

View File

@ -20,20 +20,20 @@ fn r#if() {
assert_eq!(Value::Integer(1), value); assert_eq!(Value::Integer(1), value);
let value = eval("if(false, 1)").unwrap(); let value = eval("if(false, 1)").unwrap();
assert!(value.is_empty()); assert_eq!(Value::Empty, value);
} }
#[test] #[test]
fn r#if_else() { 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); 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); 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); 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); assert_eq!(Value::Integer(2), value);
} }