Implement if
This commit is contained in:
parent
f15c8ef2ef
commit
f0c759d92a
@ -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.
|
||||||
|
@ -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
|
|
||||||
])],
|
])],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user