New set_new and is_set commands

This commit is contained in:
sagie gur ari 2020-05-05 06:33:27 +00:00
parent 1ef91e3fa7
commit 67ab71d93d
11 changed files with 365 additions and 1 deletions

View file

@ -2,6 +2,8 @@
### v0.3.4
* New set_new command.
* New is_set command.
* New unset command.
* New array_contains command.
* New map_contains_value command.

View file

@ -18,6 +18,7 @@
* [std::collections::ArraySet (array_set)](#std__collections__ArraySet)
* [std::collections::IsArray (is_array)](#std__collections__IsArray)
* [std::collections::IsMap (is_map)](#std__collections__IsMap)
* [std::collections::IsSet (is_set)](#std__collections__IsSet)
* [std::collections::Map (map)](#std__collections__Map)
* [std::collections::MapClear (map_clear)](#std__collections__MapClear)
* [std::collections::MapContainsKey (map_contains_key)](#std__collections__MapContainsKey)
@ -32,6 +33,7 @@
* [std::collections::MapToProperties (map_to_properties)](#std__collections__MapToProperties)
* [std::collections::Range (range)](#std__collections__Range)
* [std::collections::ReadProperties (read_properties)](#std__collections__ReadProperties)
* [std::collections::Set (set_new)](#std__collections__Set)
* [std::collections::WriteProperties (write_properties)](#std__collections__WriteProperties)
* [std::debug::DuckscriptSDKVersion (duckscript_sdk_version)](#std__debug__DuckscriptSDKVersion)
* [std::debug::DuckscriptVersion (duckscript_version)](#std__debug__DuckscriptVersion)
@ -876,6 +878,38 @@ assert ${released}
#### Aliases:
is_map
<a name="std__collections__IsSet"></a>
## std::collections::IsSet
```sh
var = is_set handle
```
Returns true if the provided value is a set handle.
#### Parameters
The set handle.
#### Return Value
True if the provided value is a set handle.
#### Examples
```sh
handle = set_new 1 2 3
value = is_set ${handle}
assert ${value}
released = release ${handle}
assert ${released}
```
#### Aliases:
is_set
<a name="std__collections__Map"></a>
## std::collections::Map
```sh
@ -1404,6 +1438,37 @@ assert_eq ${config.a.b.c} 3
#### Aliases:
read_properties
<a name="std__collections__Set"></a>
## std::collections::Set
```sh
handle = set_new value1 value2 value3 ...
```
Creates a new set from the input arguments and returns a handle to that set.<br>
This handle can be passed to other commands which support sets using handles.<br>
Once the set is no longer used, it should be released using the **release** command.
#### Parameters
Any number of arguments which will construct the set.
#### Return Value
A handle to the set.
#### Examples
```sh
handle = set_new ${var} "hello world" 5 ${another_var}
# once done we should release the handle
release ${handle}
```
#### Aliases:
set_new
<a name="std__collections__WriteProperties"></a>
## std::collections::WriteProperties
```sh

View file

@ -38,7 +38,7 @@ pub enum StateValue {
/// list
List(Vec<StateValue>),
/// unique set of values
Set(HashSet<StateValue>),
Set(HashSet<String>),
/// sub state value
SubState(HashMap<String, StateValue>),
/// any value

View file

@ -0,0 +1,25 @@
```sh
var = is_set handle
```
Returns true if the provided value is a set handle.
#### Parameters
The set handle.
#### Return Value
True if the provided value is a set handle.
#### Examples
```sh
handle = set_new 1 2 3
value = is_set ${handle}
assert ${value}
released = release ${handle}
assert ${released}
```

View file

@ -0,0 +1,70 @@
use crate::utils::pckg;
use crate::utils::state::get_handles_sub_state;
use duckscript::types::command::{Command, CommandResult, Commands};
use duckscript::types::instruction::Instruction;
use duckscript::types::runtime::StateValue;
use std::collections::HashMap;
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "IsSet")
}
fn aliases(&self) -> Vec<String> {
vec!["is_set".to_string()]
}
fn help(&self) -> String {
include_str!("help.md").to_string()
}
fn clone_and_box(&self) -> Box<dyn Command> {
Box::new((*self).clone())
}
fn requires_context(&self) -> bool {
true
}
fn run_with_context(
&self,
arguments: Vec<String>,
state: &mut HashMap<String, StateValue>,
_variables: &mut HashMap<String, String>,
_output_variable: Option<String>,
_instructions: &Vec<Instruction>,
_commands: &mut Commands,
_line: usize,
) -> CommandResult {
if arguments.is_empty() {
CommandResult::Error("Set handle not provided.".to_string())
} else {
let state = get_handles_sub_state(state);
let key = &arguments[0];
match state.get(key) {
Some(state_value) => match state_value {
StateValue::Set(_) => CommandResult::Continue(Some("true".to_string())),
_ => CommandResult::Continue(Some("false".to_string())),
},
None => CommandResult::Continue(Some("false".to_string())),
}
}
}
}
pub(crate) fn create(package: &str) -> Box<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View file

@ -0,0 +1,47 @@
use super::*;
use crate::sdk::std::collections::set;
use crate::test;
use crate::test::{CommandValidation, SetCommand};
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
test::run_script_and_error(vec![create("")], "out = is_set", "out");
}
#[test]
fn run_not_found() {
test::run_script_and_validate(
vec![create("")],
"out = is_set bad_handle",
CommandValidation::Match("out".to_string(), "false".to_string()),
);
}
#[test]
fn run_not_set() {
test::run_script_and_validate(
vec![create(""), Box::new(SetCommand {})],
r#"
handle = test_set true
out = is_set ${handle}
"#,
CommandValidation::Match("out".to_string(), "false".to_string()),
);
}
#[test]
fn run_found() {
test::run_script_and_validate(
vec![create(""), set::create("")],
r#"
handle = set_new a b c "d e"
out = is_set ${handle}
"#,
CommandValidation::Match("out".to_string(), "true".to_string()),
);
}

View file

@ -10,6 +10,7 @@ mod array_push;
mod array_set;
mod is_array;
mod is_map;
mod is_set;
mod map;
mod map_clear;
mod map_contains_key;
@ -24,6 +25,7 @@ mod map_size;
mod map_to_properties;
mod range;
mod read_properties;
mod set;
mod write_properties;
use crate::utils::pckg;
@ -47,6 +49,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(array_pop::create(&package))?;
commands.set(is_array::create(&package))?;
commands.set(is_map::create(&package))?;
commands.set(is_set::create(&package))?;
commands.set(map::create(&package))?;
commands.set(map_clear::create(&package))?;
commands.set(map_contains_key::create(&package)?)?;
@ -61,6 +64,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(map_to_properties::create(&package))?;
commands.set(range::create(&package))?;
commands.set(read_properties::create(&package))?;
commands.set(set::create(&package))?;
commands.set(write_properties::create(&package))?;
Ok(())

View file

@ -0,0 +1,24 @@
```sh
handle = set_new value1 value2 value3 ...
```
Creates a new set from the input arguments and returns a handle to that set.<br>
This handle can be passed to other commands which support sets using handles.<br>
Once the set is no longer used, it should be released using the **release** command.
#### Parameters
Any number of arguments which will construct the set.
#### Return Value
A handle to the set.
#### Examples
```sh
handle = set_new ${var} "hello world" 5 ${another_var}
# once done we should release the handle
release ${handle}
```

View file

@ -0,0 +1,64 @@
use crate::utils::pckg;
use crate::utils::state::put_handle;
use duckscript::types::command::{Command, CommandResult, Commands};
use duckscript::types::instruction::Instruction;
use duckscript::types::runtime::StateValue;
use std::collections::{HashMap, HashSet};
#[cfg(test)]
#[path = "./mod_test.rs"]
mod mod_test;
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
}
impl Command for CommandImpl {
fn name(&self) -> String {
pckg::concat(&self.package, "Set")
}
fn aliases(&self) -> Vec<String> {
vec!["set_new".to_string()]
}
fn help(&self) -> String {
include_str!("help.md").to_string()
}
fn clone_and_box(&self) -> Box<dyn Command> {
Box::new((*self).clone())
}
fn requires_context(&self) -> bool {
true
}
fn run_with_context(
&self,
arguments: Vec<String>,
state: &mut HashMap<String, StateValue>,
_variables: &mut HashMap<String, String>,
_output_variable: Option<String>,
_instructions: &Vec<Instruction>,
_commands: &mut Commands,
_line: usize,
) -> CommandResult {
let mut set = HashSet::new();
for argument in arguments {
set.insert(argument);
}
let key = put_handle(state, StateValue::Set(set));
CommandResult::Continue(Some(key))
}
}
pub(crate) fn create(package: &str) -> Box<dyn Command> {
Box::new(CommandImpl {
package: package.to_string(),
})
}

View file

@ -0,0 +1,41 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
use crate::utils::state::get_handles_sub_state;
#[test]
fn common_functions() {
test::test_common_command_functions(create(""));
}
#[test]
fn run_no_args() {
let mut context = test::run_script_and_validate(
vec![create("")],
"out = set_new",
CommandValidation::Contains("out".to_string(), "handle:".to_string()),
);
let state = get_handles_sub_state(&mut context.state);
let list_value = state.get(context.variables.get("out").unwrap()).unwrap();
match list_value {
StateValue::Set(set) => assert!(set.is_empty()),
_ => panic!("Invalid handle type."),
}
}
#[test]
fn run_with_args() {
let mut context = test::run_script_and_validate(
vec![create("")],
r#"out = set_new 1 "hello world" test"#,
CommandValidation::Contains("out".to_string(), "handle:".to_string()),
);
let state = get_handles_sub_state(&mut context.state);
let list_value = state.remove(context.variables.get("out").unwrap()).unwrap();
match list_value {
StateValue::Set(set) => assert_eq!(set.len(), 3),
_ => panic!("Invalid handle type."),
}
}

View file

@ -0,0 +1,22 @@
fn test_set_found
set_handle = set_new
value = is_set ${set_handle}
assert ${value}
released = release ${set_handle}
assert ${released}
end
fn test_not_set
set_handle = set true
value = is_set ${set_handle}
assert_false ${value}
end
fn test_not_found
value = is_set ${set_handle}
assert_false ${value}
end