Merge pull request #182 from sagiegurari/0.8.4

0.8.4
This commit is contained in:
Sagie Gur-Ari 2021-07-10 01:28:58 +03:00 committed by GitHub
commit cd540244f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 412 additions and 79 deletions

View file

@ -1,5 +1,14 @@
## CHANGELOG
### v0.8.4
* New --collection flag to json_parse command which returns maps/arrays instead of variables #175
* New --collection flag to json_encode command which encodes maps/arrays instead of variables #175
### v0.8.3
* Fix release with recursive flag to support set data structures as well.
### v0.8.2 (2021-06-04)
* Upgrade dependencies #179

24
Cargo.lock generated
View file

@ -454,9 +454,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.95"
version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]]
name = "log"
@ -585,9 +585,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.7.2"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "openssl"
@ -672,9 +672,9 @@ dependencies = [
[[package]]
name = "rand_chacha"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
@ -779,9 +779,9 @@ dependencies = [
[[package]]
name = "security-framework"
version = "2.2.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3670b1d2fdf6084d192bc71ead7aabe6c06aa2ea3fbd9cc3ac111fa5c2b1bd84"
checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467"
dependencies = [
"bitflags",
"core-foundation",
@ -792,9 +792,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3676258fd3cfe2c9a0ec99ce3038798d847ce3e4bb17746373eb9f0f1ac16339"
checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284"
dependencies = [
"core-foundation-sys",
"libc",
@ -825,9 +825,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.72"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
dependencies = [
"proc-macro2",
"quote",

View file

@ -172,6 +172,7 @@
* [std::time::CurrentTimeMillies (current_time)](#std__time__CurrentTimeMillies)
* [std::var::GetAllVarNames (get_all_var_names)](#std__var__GetAllVarNames)
* [std::var::GetByName (get_by_name)](#std__var__GetByName)
* [std::var::IsDefined (is_defined)](#std__var__IsDefined)
* [std::var::Set (set)](#std__var__Set)
* [std::var::SetByName (set_by_name)](#std__var__SetByName)
* [std::var::Unset (unset)](#std__var__Unset)
@ -410,12 +411,12 @@ release [-r|--recursive] handle
Releases an internal handle stored in the runtime memory.<br>
Certain commands (such as **array**) will create a handle and the variable will only hold a reference to that handle.<br>
In order to release those handles once they are no longer needed, the release command should be used.<br>
By providing the recursive flag, it will also go over the data values (array items, map values, ...) and release each one of them as well
if they are handles to other arrays/maps/...
By providing the recursive flag, it will also go over the data values (array items, map values, set keys, ...) and release each one of them as well
if they are handles to other arrays/maps/sets/...
#### Parameters
* Optional recursive flag (default false)
* Optional recursive (-r/--recursive) flag (default false)
* The handle name.
#### Return Value
@ -4104,11 +4105,14 @@ string = json_encode var_name
```
This function will encode all variables, starting from the root variable as a JSON string.<br>
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.<br>
If --collection is passed, the provided value is considered as string or a map/array handle which is used to fetch
the tree data and create the json string.
#### Parameters
The root variable name
* Option --collection flag to make the encoding use the maps/arrays and values
* The root variable name (or a handle/value in case --collection is provided)
#### Return Value
@ -4117,8 +4121,13 @@ The JSON string
#### Examples
```sh
# will parse and encode to plain variables
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
jsonstring = json_encode package
# will parse and encode to maps/arrays
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
jsonstring = json_encode --collection ${package}
```
@ -4141,17 +4150,23 @@ root.child[5]
root.child.length
```
In case the --collection flag is provided, it will instead create maps/array as needed and return the root handle (or primitive value) of
the json data.
Make sure to use the release with the recursive flag on the root object to release the entire memory once done.
#### Parameters
The JSON string to parse.
* Optional --collection flag to parse and return value/map/array
* The JSON string to parse.
#### Return Value
The root value.
The root value/handle.
#### Examples
```sh
# parse to simple variables
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
assert_eq ${package} "[OBJECT]"
@ -4162,6 +4177,26 @@ assert_eq ${package.keywords.length} 2
assert_eq ${package.keywords[0]} test1
assert_eq ${package.keywords[1]} test2
assert_eq ${package.directories.test} spec
# parse to maps/arrays
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
name = map_get ${package} name
assert_eq ${name} "my package"
version = map_get ${package} version
assert_eq ${version} 1
public = map_get ${package} public
assert_false ${public}
keywords_handle = map_get ${package} keywords
length = array_length ${keywords_handle}
assert_eq ${length} 2
value = array_pop ${keywords_handle}
assert_eq ${value} test2
value = array_pop ${keywords_handle}
assert_eq ${value} test1
directories = map_get ${package} directories
directory = map_get ${directories} test
assert_eq ${directory} spec
release --recursive ${package}
```
@ -6338,6 +6373,33 @@ assert_eq ${value} test
#### Aliases:
get_by_name
<a name="std__var__IsDefined"></a>
## std::var::IsDefined
```sh
var = is_defined key
```
Returns true if the provided variable name (not value) exists.
#### Parameters
The variable name.
#### Return Value
True if the variable is defined.
#### Examples
```sh
key = set "hello world"
exists = is_defined key
```
#### Aliases:
is_defined
<a name="std__var__Set"></a>
## std::var::Set
```sh

View file

@ -3,11 +3,14 @@ string = json_encode var_name
```
This function will encode all variables, starting from the root variable as a JSON string.<br>
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.
Since duckscript is untyped, all boolean and numeric values will be encoded as strings.<br>
If --collection is passed, the provided value is considered as string or a map/array handle which is used to fetch
the tree data and create the json string.
#### Parameters
The root variable name
* Option --collection flag to make the encoding use the maps/arrays and values
* The root variable name (or a handle/value in case --collection is provided)
#### Return Value
@ -16,6 +19,11 @@ The JSON string
#### Examples
```sh
# will parse and encode to plain variables
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
jsonstring = json_encode package
# will parse and encode to maps/arrays
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
jsonstring = json_encode --collection ${package}
```

View file

@ -1,10 +1,11 @@
use crate::sdk::std::json::OBJECT_VALUE;
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 serde_json::map::Map;
use serde_json::Value;
use serde_json::{Number, Value};
use std::collections::{HashMap, HashSet};
#[cfg(test)]
@ -92,7 +93,10 @@ fn encode_any(name: &str, values: &HashMap<&str, &str>) -> Result<Value, String>
}
}
fn encode(name: &str, variables: &HashMap<String, String>) -> Result<String, String> {
fn encode_from_variables(
name: &str,
variables: &HashMap<String, String>,
) -> Result<String, String> {
let mut object_variables: HashMap<&str, &str> = HashMap::new();
for (key, value) in variables {
@ -111,6 +115,68 @@ fn encode(name: &str, variables: &HashMap<String, String>) -> Result<String, Str
}
}
fn encode_from_state_value(
state_value: &StateValue,
state: &HashMap<String, StateValue>,
) -> Result<Value, String> {
match state_value {
StateValue::Boolean(value) => Ok(Value::Bool(*value)),
StateValue::Number(value) => Ok(Value::Number(Number::from(*value))),
StateValue::UnsignedNumber(value) => Ok(Value::Number(Number::from(*value))),
StateValue::Number32Bit(value) => Ok(Value::Number(Number::from(*value))),
StateValue::UnsignedNumber32Bit(value) => Ok(Value::Number(Number::from(*value))),
StateValue::Number64Bit(value) => Ok(Value::Number(Number::from(*value))),
StateValue::UnsignedNumber64Bit(value) => Ok(Value::Number(Number::from(*value))),
StateValue::String(value) => match state.get(value) {
Some(sub_state_value) => encode_from_state_value(sub_state_value, state),
None => Ok(Value::String(value.to_string())),
},
StateValue::List(list) => {
let mut items = vec![];
for item in list {
match encode_from_state_value(item, state) {
Ok(item_value) => {
items.push(item_value);
}
Err(error) => return Err(error),
};
}
Ok(Value::Array(items))
}
StateValue::SubState(sub_state) => {
let mut items = Map::new();
for (key, value) in sub_state {
match encode_from_state_value(value, state) {
Ok(item_value) => {
items.insert(key.to_string(), item_value);
}
Err(error) => return Err(error),
}
}
Ok(Value::Object(items))
}
StateValue::ByteArray(_) => Err("Unsupported value type.".to_string()),
StateValue::Set(_) => Err("Unsupported value type.".to_string()),
StateValue::Any(_) => Err("Unsupported value type.".to_string()),
}
}
fn encode_from_state(value: &str, state: &HashMap<String, StateValue>) -> Result<String, String> {
let json_value = match state.get(value) {
Some(state_value) => encode_from_state_value(state_value, state),
None => Ok(Value::String(value.to_string())),
};
match json_value {
Ok(json_value_obj) => Ok(json_value_obj.to_string()),
Err(error) => Err(error.to_string()),
}
}
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
@ -140,7 +206,7 @@ impl Command for CommandImpl {
fn run_with_context(
&self,
arguments: Vec<String>,
_state: &mut HashMap<String, StateValue>,
state: &mut HashMap<String, StateValue>,
variables: &mut HashMap<String, String>,
_output_variable: Option<String>,
_instructions: &Vec<Instruction>,
@ -150,9 +216,24 @@ impl Command for CommandImpl {
if arguments.is_empty() {
CommandResult::Error("No JSON root variable name provided.".to_string())
} else {
match encode(&arguments[0], variables) {
Ok(output) => CommandResult::Continue(Some(output)),
Err(error) => CommandResult::Error(error),
let (start_index, as_state) = if arguments.len() > 1 && arguments[0] == "--collection" {
(1, true)
} else {
(0, false)
};
if as_state {
let state = get_handles_sub_state(state);
match encode_from_state(&arguments[start_index], state) {
Ok(output) => CommandResult::Continue(Some(output)),
Err(error) => CommandResult::Error(error),
}
} else {
match encode_from_variables(&arguments[start_index], variables) {
Ok(output) => CommandResult::Continue(Some(output)),
Err(error) => CommandResult::Error(error),
}
}
}
}

View file

@ -12,17 +12,23 @@ root.child[5]
root.child.length
```
In case the --collection flag is provided, it will instead create maps/array as needed and return the root handle (or primitive value) of
the json data.
Make sure to use the release with the recursive flag on the root object to release the entire memory once done.
#### Parameters
The JSON string to parse.
* Optional --collection flag to parse and return value/map/array
* The JSON string to parse.
#### Return Value
The root value.
The root value/handle.
#### Examples
```sh
# parse to simple variables
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
assert_eq ${package} "[OBJECT]"
@ -33,4 +39,24 @@ assert_eq ${package.keywords.length} 2
assert_eq ${package.keywords[0]} test1
assert_eq ${package.keywords[1]} test2
assert_eq ${package.directories.test} spec
# parse to maps/arrays
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
name = map_get ${package} name
assert_eq ${name} "my package"
version = map_get ${package} version
assert_eq ${version} 1
public = map_get ${package} public
assert_false ${public}
keywords_handle = map_get ${package} keywords
length = array_length ${keywords_handle}
assert_eq ${length} 2
value = array_pop ${keywords_handle}
assert_eq ${value} test2
value = array_pop ${keywords_handle}
assert_eq ${value} test1
directories = map_get ${package} directories
directory = map_get ${directories} test
assert_eq ${directory} spec
release --recursive ${package}
```

View file

@ -1,5 +1,6 @@
use crate::sdk::std::json::OBJECT_VALUE;
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;
@ -46,6 +47,41 @@ fn create_variables(data: Value, name: &str, variables: &mut HashMap<String, Str
};
}
fn create_structure(data: Value, state: &mut HashMap<String, StateValue>) -> Option<String> {
match data {
Value::Null => None,
Value::Bool(value) => Some(value.to_string()),
Value::Number(value) => Some(value.to_string()),
Value::String(value) => Some(value),
Value::Array(list) => {
let mut state_list = vec![];
for item in list {
if let Some(value) = create_structure(item, state) {
state_list.push(StateValue::String(value));
}
}
let key = put_handle(state, StateValue::List(state_list));
Some(key)
}
Value::Object(map) => {
let mut state_map = HashMap::new();
for (key, value) in map {
if let Some(value) = create_structure(value, state) {
state_map.insert(key, StateValue::String(value));
}
}
let key = put_handle(state, StateValue::SubState(state_map));
Some(key)
}
}
}
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
@ -75,7 +111,7 @@ impl Command for CommandImpl {
fn run_with_context(
&self,
arguments: Vec<String>,
_state: &mut HashMap<String, StateValue>,
state: &mut HashMap<String, StateValue>,
variables: &mut HashMap<String, String>,
output_variable: Option<String>,
_instructions: &Vec<Instruction>,
@ -85,15 +121,25 @@ impl Command for CommandImpl {
if arguments.is_empty() {
CommandResult::Error("No JSON string provided.".to_string())
} else {
match parse_json(&arguments[0]) {
let (json_index, as_state) = if arguments.len() > 1 && arguments[0] == "--collection" {
(1, true)
} else {
(0, false)
};
match parse_json(&arguments[json_index]) {
Ok(data) => {
let output = match output_variable {
Some(name) => {
create_variables(data, &name, variables);
if as_state {
create_structure(data, state)
} else {
create_variables(data, &name, variables);
match variables.get(&name) {
Some(value) => Some(value.to_string()),
None => None,
match variables.get(&name) {
Some(value) => Some(value.to_string()),
None => None,
}
}
}
None => Some("true".to_string()),

View file

@ -13,7 +13,7 @@ fn run_no_args() {
}
#[test]
fn run_all_types() {
fn run_all_types_as_vars() {
let context = test::run_script_and_validate(
vec![create("")],
r#"

View file

@ -5,12 +5,12 @@ release [-r|--recursive] handle
Releases an internal handle stored in the runtime memory.<br>
Certain commands (such as **array**) will create a handle and the variable will only hold a reference to that handle.<br>
In order to release those handles once they are no longer needed, the release command should be used.<br>
By providing the recursive flag, it will also go over the data values (array items, map values, ...) and release each one of them as well
if they are handles to other arrays/maps/...
By providing the recursive flag, it will also go over the data values (array items, map values, set keys, ...) and release each one of them as well
if they are handles to other arrays/maps/sets/...
#### Parameters
* Optional recursive flag (default false)
* Optional recursive (-r/--recursive) flag (default false)
* The handle name.
#### Return Value

View file

@ -1,5 +1,5 @@
use crate::utils::pckg;
use crate::utils::state::remove_handle;
use crate::utils::state::{remove_handle, remove_handle_recursive};
use duckscript::types::command::{Command, CommandResult, Commands};
use duckscript::types::instruction::Instruction;
use duckscript::types::runtime::StateValue;
@ -9,41 +9,6 @@ use std::collections::HashMap;
#[path = "./mod_test.rs"]
mod mod_test;
fn remove(state: &mut HashMap<String, StateValue>, key: &str, recursive: bool) -> bool {
match remove_handle(state, key.to_string()) {
Some(state_value) => {
if recursive {
match state_value {
StateValue::SubState(map) => {
for (_, map_value) in map {
match map_value {
StateValue::String(value) => remove(state, &value, recursive),
_ => true,
};
}
true
}
StateValue::List(list) => {
for value in list {
match value {
StateValue::String(value) => remove(state, &value, recursive),
_ => true,
};
}
true
}
_ => true,
}
} else {
true
}
}
None => false,
}
}
#[derive(Clone)]
pub(crate) struct CommandImpl {
package: String,
@ -90,7 +55,12 @@ impl Command for CommandImpl {
(arguments[0].to_string(), false)
};
let removed = remove(state, &key, recursive);
let removed = if recursive {
remove_handle_recursive(state, key)
} else {
let old_value = remove_handle(state, key);
old_value.is_some()
};
CommandResult::Continue(Some(removed.to_string()))
}

View file

@ -17,7 +17,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr
commands.set(get_all_var_names::create(&package))?;
commands.set(get_by_name::create(&package))?;
commands.set(is_defined::create(PACKAGE))?;
commands.set(is_defined::create(&package))?;
commands.set(set::create(&package))?;
commands.set(set_by_name::create(&package))?;
commands.set(unset::create(&package)?)?;

View file

@ -68,6 +68,43 @@ pub(crate) fn remove_handle(
handle_state.remove(&key)
}
pub(crate) fn remove_handle_recursive(
state: &mut HashMap<String, StateValue>,
key: String,
) -> bool {
match remove_handle(state, key.to_string()) {
Some(state_value) => match state_value {
StateValue::List(list) => {
for value in list {
if let StateValue::String(value) = value {
remove_handle_recursive(state, value);
};
}
true
}
StateValue::Set(set) => {
for value in set {
remove_handle_recursive(state, value);
}
true
}
StateValue::SubState(map) => {
for (_, map_value) in map {
if let StateValue::String(value) = map_value {
remove_handle_recursive(state, value);
};
}
true
}
_ => true,
},
None => false,
}
}
pub(crate) fn return_handle(
state: &mut HashMap<String, StateValue>,
key: String,

View file

@ -52,7 +52,7 @@ fn test_simple_types
assert_false ${defined}
end
fn test_all_types
fn test_all_types_as_vars
jsonstring = set "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
package = json_parse ${jsonstring}
@ -98,3 +98,43 @@ fn test_all_types
assert_eq ${package2.keywords[1].directories.test} spec
end
fn test_all_types_as_collections
jsonstring = set "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
package = json_parse --collection ${jsonstring}
name = map_get ${package} name
assert_eq ${name} "my package"
version = map_get ${package} version
assert_eq ${version} 1
public = map_get ${package} public
assert_false ${public}
keywords_handle = map_get ${package} keywords
length = array_length ${keywords_handle}
assert_eq ${length} 2
value = array_get ${keywords_handle} 0
assert_eq ${value} test1
value = array_get ${keywords_handle} 1
assert_eq ${value} test2
directories = map_get ${package} directories
directory = map_get ${directories} test
assert_eq ${directory} spec
map_put ${package} name "my package 2"
name = map_get ${package} name
assert_eq ${name} "my package 2"
update_jsonstring = json_encode --collection ${package}
release --recursive ${package}
package2 = json_parse ${update_jsonstring}
assert_eq ${package2} "[OBJECT]"
assert_eq ${package2.name} "my package 2"
assert_eq ${package2.version} 1
assert_eq ${package2.publish} false
assert_eq ${package2.keywords.length} 2
assert_eq ${package2.keywords[0]} test1
assert_eq ${package2.keywords[1]} test2
assert_eq ${package2.directories.test} spec
end

View file

@ -1,5 +1,5 @@
fn test_all_types
fn test_all_types_as_vars
package = json_parse "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
assert_eq ${package} "[OBJECT]"
@ -12,3 +12,45 @@ fn test_all_types
assert_eq ${package.directories.test} spec
end
fn test_all_types_as_collections
package = json_parse --collection "{\"name\": \"my package\", \"version\": 1, \"publish\": false, \"keywords\": [\"test1\", \"test2\"], \"directories\": {\"test\": \"spec\"}}"
output = is_map ${package}
assert ${output}
name = map_get ${package} name
assert_eq ${name} "my package"
version = map_get ${package} version
assert_eq ${version} 1
public = map_get ${package} public
assert_false ${public}
keywords_handle = map_get ${package} keywords
output = is_array ${keywords_handle}
assert ${output}
length = array_length ${keywords_handle}
assert_eq ${length} 2
value = array_pop ${keywords_handle}
assert_eq ${value} test2
value = array_pop ${keywords_handle}
assert_eq ${value} test1
directories = map_get ${package} directories
output = is_map ${directories}
assert ${output}
directory = map_get ${directories} test
assert_eq ${directory} spec
release --recursive ${package}
output = is_map ${package}
assert_false ${output}
output = is_array ${keywords_handle}
assert_false ${output}
output = is_map ${directories}
assert_false ${output}
end

View file

@ -20,6 +20,10 @@ fn test_release_recursive
sub_array_handle2 = array
array_handle = array ${sub_array_handle2}
sub_set_handle = set_new
set_handle = set_new ${sub_set_handle}
array_push ${array_handle} ${set_handle}
handle = array ${array_handle} ${map_handle}
exists = is_array ${handle}
@ -32,6 +36,10 @@ fn test_release_recursive
assert ${exists}
exists = is_array ${sub_array_handle2}
assert ${exists}
exists = is_set ${set_handle}
assert ${exists}
exists = is_set ${sub_set_handle}
assert ${exists}
release -r ${handle}
@ -45,4 +53,8 @@ fn test_release_recursive
assert_false ${exists}
exists = is_array ${sub_array_handle2}
assert_false ${exists}
exists = is_set ${set_handle}
assert_false ${exists}
exists = is_set ${sub_set_handle}
assert_false ${exists}
end