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.*
pub fn eval(string: &str) -> Result<Value> {
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.

View File

@ -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<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![
ValueType::List(vec![
ValueType::Boolean,
ValueType::Any,
ValueType::Any
]),
ValueType::List(vec![
ValueType::Function,
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
/// 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,

View File

@ -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);

View File

@ -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);
}