implement return in while
This commit is contained in:
parent
d9608a8f8c
commit
2829316abe
11
Cargo.toml
11
Cargo.toml
|
@ -21,15 +21,18 @@ zip = ["dep:zip"]
|
|||
|
||||
[dependencies]
|
||||
chksum-md5 = "0.1.0"
|
||||
getset = "0.1.5"
|
||||
getset = "0.1.6"
|
||||
serde = { version = "1.0.219", optional = true, features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
serde_json = "1.0.143"
|
||||
tracing = "0.1.41"
|
||||
zip = { version = "4.0.0", default-features = false, features = ["deflate", "time"], optional = true }
|
||||
zip = { version = "5.1.0", default-features = false, features = ["deflate", "time"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.20.0"
|
||||
tempfile = "3.22.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[package.metadata.cargo-feature-combinations]
|
||||
exclude_features = [ "default" ]
|
|
@ -334,7 +334,6 @@ impl Group {
|
|||
let (prepare_data_storage, function_invocation) = get_group_invocation_commands(
|
||||
&function_path,
|
||||
namespace,
|
||||
commands,
|
||||
&contained_macros,
|
||||
block_pass_macros,
|
||||
macro_data_storage_name,
|
||||
|
@ -570,7 +569,6 @@ impl Hash for Group {
|
|||
fn get_group_invocation_commands(
|
||||
function_path: &str,
|
||||
namespace: &str,
|
||||
commands: &[Command],
|
||||
contained_macros: &HashSet<&str>,
|
||||
block_pass_macros: Option<&HashSet<String>>,
|
||||
macro_data_storage_name: Option<&str>,
|
||||
|
@ -579,25 +577,27 @@ fn get_group_invocation_commands(
|
|||
|
||||
let mut function_invocation = format!("function {namespace}:{function_path}");
|
||||
|
||||
if commands.contains_macros() {
|
||||
if contained_macros.is_empty() {
|
||||
(None, Command::Raw(function_invocation))
|
||||
} else {
|
||||
// WARNING: this seems to be the only way to pass macros to the function called.
|
||||
// Because everything is passed as a string, it looses one "level" of escaping per pass.
|
||||
let mut macros_parts = contained_macros
|
||||
.iter()
|
||||
.filter(|&&m| block_pass_macros.is_none_or(|b| !b.contains(m)))
|
||||
.flat_map(|&m| {
|
||||
vec![
|
||||
.map(|&m| {
|
||||
[
|
||||
MacroStringPart::String(format!(r#"{m}:""#)),
|
||||
MacroStringPart::MacroUsage(m.to_string()),
|
||||
MacroStringPart::String(r#"""#.to_string()),
|
||||
]
|
||||
})
|
||||
.fold(Vec::new(), |mut acc, part| {
|
||||
.fold(Vec::new(), |mut acc, parts| {
|
||||
if !acc.is_empty() {
|
||||
acc.push(MacroStringPart::String(",".to_string()));
|
||||
}
|
||||
|
||||
acc.push(part);
|
||||
acc.extend(parts);
|
||||
|
||||
acc
|
||||
});
|
||||
|
@ -632,8 +632,6 @@ fn get_group_invocation_commands(
|
|||
|
||||
(None, Command::UsesMacro(macro_string))
|
||||
}
|
||||
} else {
|
||||
(None, Command::Raw(function_invocation))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -777,16 +775,11 @@ impl While {
|
|||
for cmd in &self.commands {
|
||||
macros.extend(cmd.get_macros());
|
||||
}
|
||||
macros.extend(self.condition.get_macros());
|
||||
macros
|
||||
};
|
||||
let (prepare_data_storage, function_invocation) = get_group_invocation_commands(
|
||||
&function_path,
|
||||
namespace,
|
||||
&self.commands,
|
||||
&contained_macros,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let (prepare_data_storage, function_invocation) =
|
||||
get_group_invocation_commands(&function_path, namespace, &contained_macros, None, None);
|
||||
|
||||
let execute_tail = if let Some(prepare_datastorage_cmd) = prepare_data_storage {
|
||||
Execute::Runs(vec![prepare_datastorage_cmd, function_invocation])
|
||||
|
@ -807,20 +800,105 @@ impl While {
|
|||
let contains_return = commands.contains_return();
|
||||
|
||||
if contains_return {
|
||||
todo!("While loops with return commands are not yet supported");
|
||||
}
|
||||
let full_path = format!(
|
||||
"{namespace}:{function_path}",
|
||||
namespace = function_state.namespace()
|
||||
);
|
||||
let return_data_path = md5::hash(&full_path).to_hex_lowercase();
|
||||
|
||||
conditional_run_cmd.compile(options, global_state, function_state)
|
||||
let mut pre_cmds = Command::Raw(format!(
|
||||
"data remove storage shulkerbox:return {return_data_path}"
|
||||
))
|
||||
.compile(options, global_state, function_state)
|
||||
.into_iter()
|
||||
.map(|c| c.with_forbid_prefix(true))
|
||||
.collect::<Vec<_>>();
|
||||
let post_condition = Condition::Atom(
|
||||
format!("data storage shulkerbox:return {return_data_path}").into(),
|
||||
);
|
||||
|
||||
let post_cmd_store = global_state
|
||||
.read()
|
||||
.unwrap()
|
||||
.functions_with_special_return
|
||||
.get(&format!(
|
||||
"{}:{}",
|
||||
function_state.namespace(),
|
||||
function_state.path()
|
||||
))
|
||||
.cloned().map(|parent_return_data_path| {
|
||||
Command::Execute(Execute::If(
|
||||
post_condition.clone(),
|
||||
Box::new(Execute::Run(Box::new(Command::Raw(format!(
|
||||
"data modify storage shulkerbox:return {parent_return_data_path} set from storage shulkerbox:return {return_data_path}"
|
||||
))))),
|
||||
None,
|
||||
))
|
||||
});
|
||||
|
||||
let post_cmd_return = Command::Execute(Execute::If(
|
||||
post_condition,
|
||||
Box::new(Execute::Run(Box::new(Command::Raw(format!(
|
||||
"return run data get storage shulkerbox:return {return_data_path}"
|
||||
))))),
|
||||
None,
|
||||
));
|
||||
|
||||
let post_cmds = post_cmd_store
|
||||
.into_iter()
|
||||
.chain(std::iter::once(post_cmd_return))
|
||||
.flat_map(|cmd| cmd.compile(options, global_state, function_state))
|
||||
.map(|c| c.with_forbid_prefix(true))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
global_state
|
||||
.write()
|
||||
.unwrap()
|
||||
.functions_with_special_return
|
||||
.insert(full_path, return_data_path);
|
||||
|
||||
pre_cmds.extend(conditional_run_cmd.compile(options, global_state, function_state));
|
||||
pre_cmds.extend(post_cmds);
|
||||
pre_cmds
|
||||
} else {
|
||||
conditional_run_cmd.compile(options, global_state, function_state)
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_count(&self, options: &CompileOptions) -> usize {
|
||||
Execute::If(
|
||||
let if_count = Execute::If(
|
||||
self.condition.clone(),
|
||||
Box::new(Execute::Run(Box::new(Command::Raw(String::new())))),
|
||||
None,
|
||||
)
|
||||
.get_count(options)
|
||||
.get_count(options);
|
||||
|
||||
let additional_return_cmds = if self.contains_return() {
|
||||
let post_cmd_store = Command::Execute(Execute::If(
|
||||
Condition::Atom("".into()),
|
||||
Box::new(Execute::Run(Box::new(Command::Raw(String::new())))),
|
||||
None,
|
||||
))
|
||||
.get_count(options);
|
||||
|
||||
let post_cmd_return = Command::Execute(Execute::If(
|
||||
Condition::Atom("".into()),
|
||||
Box::new(Execute::Run(Box::new(Command::Raw(String::new())))),
|
||||
None,
|
||||
))
|
||||
.get_count(options);
|
||||
|
||||
let post_cmds = post_cmd_store + post_cmd_return;
|
||||
|
||||
Some(post_cmds + 1)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
additional_return_cmds.map_or(if_count, |additional_return_cmds| {
|
||||
additional_return_cmds + if_count
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
)]
|
||||
#![warn(clippy::all, clippy::pedantic, clippy::perf)]
|
||||
#![allow(clippy::missing_panics_doc, clippy::missing_const_for_fn)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
|
||||
pub mod datapack;
|
||||
pub mod util;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[cfg(feature = "zip")]
|
||||
#[cfg(all(feature = "fs_access", feature = "zip"))]
|
||||
use zip::ZipWriter;
|
||||
|
||||
/// Folder representation in virtual file system
|
||||
|
|
Loading…
Reference in New Issue