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]
 | 
					[dependencies]
 | 
				
			||||||
chksum-md5 = "0.1.0"
 | 
					chksum-md5 = "0.1.0"
 | 
				
			||||||
getset = "0.1.5"
 | 
					getset = "0.1.6"
 | 
				
			||||||
serde = { version = "1.0.219", optional = true, features = ["derive"] }
 | 
					serde = { version = "1.0.219", optional = true, features = ["derive"] }
 | 
				
			||||||
serde_json = "1.0.140"
 | 
					serde_json = "1.0.143"
 | 
				
			||||||
tracing = "0.1.41"
 | 
					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]
 | 
					[dev-dependencies]
 | 
				
			||||||
tempfile = "3.20.0"
 | 
					tempfile = "3.22.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[package.metadata.docs.rs]
 | 
					[package.metadata.docs.rs]
 | 
				
			||||||
all-features = true
 | 
					all-features = true
 | 
				
			||||||
rustdoc-args = ["--cfg", "docsrs"]
 | 
					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(
 | 
					                let (prepare_data_storage, function_invocation) = get_group_invocation_commands(
 | 
				
			||||||
                    &function_path,
 | 
					                    &function_path,
 | 
				
			||||||
                    namespace,
 | 
					                    namespace,
 | 
				
			||||||
                    commands,
 | 
					 | 
				
			||||||
                    &contained_macros,
 | 
					                    &contained_macros,
 | 
				
			||||||
                    block_pass_macros,
 | 
					                    block_pass_macros,
 | 
				
			||||||
                    macro_data_storage_name,
 | 
					                    macro_data_storage_name,
 | 
				
			||||||
| 
						 | 
					@ -570,7 +569,6 @@ impl Hash for Group {
 | 
				
			||||||
fn get_group_invocation_commands(
 | 
					fn get_group_invocation_commands(
 | 
				
			||||||
    function_path: &str,
 | 
					    function_path: &str,
 | 
				
			||||||
    namespace: &str,
 | 
					    namespace: &str,
 | 
				
			||||||
    commands: &[Command],
 | 
					 | 
				
			||||||
    contained_macros: &HashSet<&str>,
 | 
					    contained_macros: &HashSet<&str>,
 | 
				
			||||||
    block_pass_macros: Option<&HashSet<String>>,
 | 
					    block_pass_macros: Option<&HashSet<String>>,
 | 
				
			||||||
    macro_data_storage_name: Option<&str>,
 | 
					    macro_data_storage_name: Option<&str>,
 | 
				
			||||||
| 
						 | 
					@ -579,25 +577,27 @@ fn get_group_invocation_commands(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut function_invocation = format!("function {namespace}:{function_path}");
 | 
					    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.
 | 
					        // 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.
 | 
					        // Because everything is passed as a string, it looses one "level" of escaping per pass.
 | 
				
			||||||
        let mut macros_parts = contained_macros
 | 
					        let mut macros_parts = contained_macros
 | 
				
			||||||
            .iter()
 | 
					            .iter()
 | 
				
			||||||
            .filter(|&&m| block_pass_macros.is_none_or(|b| !b.contains(m)))
 | 
					            .filter(|&&m| block_pass_macros.is_none_or(|b| !b.contains(m)))
 | 
				
			||||||
            .flat_map(|&m| {
 | 
					            .map(|&m| {
 | 
				
			||||||
                vec![
 | 
					                [
 | 
				
			||||||
                    MacroStringPart::String(format!(r#"{m}:""#)),
 | 
					                    MacroStringPart::String(format!(r#"{m}:""#)),
 | 
				
			||||||
                    MacroStringPart::MacroUsage(m.to_string()),
 | 
					                    MacroStringPart::MacroUsage(m.to_string()),
 | 
				
			||||||
                    MacroStringPart::String(r#"""#.to_string()),
 | 
					                    MacroStringPart::String(r#"""#.to_string()),
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .fold(Vec::new(), |mut acc, part| {
 | 
					            .fold(Vec::new(), |mut acc, parts| {
 | 
				
			||||||
                if !acc.is_empty() {
 | 
					                if !acc.is_empty() {
 | 
				
			||||||
                    acc.push(MacroStringPart::String(",".to_string()));
 | 
					                    acc.push(MacroStringPart::String(",".to_string()));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                acc.push(part);
 | 
					                acc.extend(parts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                acc
 | 
					                acc
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
| 
						 | 
					@ -632,8 +632,6 @@ fn get_group_invocation_commands(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            (None, Command::UsesMacro(macro_string))
 | 
					            (None, Command::UsesMacro(macro_string))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        (None, Command::Raw(function_invocation))
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -777,16 +775,11 @@ impl While {
 | 
				
			||||||
            for cmd in &self.commands {
 | 
					            for cmd in &self.commands {
 | 
				
			||||||
                macros.extend(cmd.get_macros());
 | 
					                macros.extend(cmd.get_macros());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            macros.extend(self.condition.get_macros());
 | 
				
			||||||
            macros
 | 
					            macros
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let (prepare_data_storage, function_invocation) = get_group_invocation_commands(
 | 
					        let (prepare_data_storage, function_invocation) =
 | 
				
			||||||
            &function_path,
 | 
					            get_group_invocation_commands(&function_path, namespace, &contained_macros, None, None);
 | 
				
			||||||
            namespace,
 | 
					 | 
				
			||||||
            &self.commands,
 | 
					 | 
				
			||||||
            &contained_macros,
 | 
					 | 
				
			||||||
            None,
 | 
					 | 
				
			||||||
            None,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let execute_tail = if let Some(prepare_datastorage_cmd) = prepare_data_storage {
 | 
					        let execute_tail = if let Some(prepare_datastorage_cmd) = prepare_data_storage {
 | 
				
			||||||
            Execute::Runs(vec![prepare_datastorage_cmd, function_invocation])
 | 
					            Execute::Runs(vec![prepare_datastorage_cmd, function_invocation])
 | 
				
			||||||
| 
						 | 
					@ -807,20 +800,105 @@ impl While {
 | 
				
			||||||
        let contains_return = commands.contains_return();
 | 
					        let contains_return = commands.contains_return();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if 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]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn get_count(&self, options: &CompileOptions) -> usize {
 | 
					    pub fn get_count(&self, options: &CompileOptions) -> usize {
 | 
				
			||||||
        Execute::If(
 | 
					        let if_count = Execute::If(
 | 
				
			||||||
            self.condition.clone(),
 | 
					            self.condition.clone(),
 | 
				
			||||||
            Box::new(Execute::Run(Box::new(Command::Raw(String::new())))),
 | 
					            Box::new(Execute::Run(Box::new(Command::Raw(String::new())))),
 | 
				
			||||||
            None,
 | 
					            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]
 | 
					    #[must_use]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@
 | 
				
			||||||
)]
 | 
					)]
 | 
				
			||||||
#![warn(clippy::all, clippy::pedantic, clippy::perf)]
 | 
					#![warn(clippy::all, clippy::pedantic, clippy::perf)]
 | 
				
			||||||
#![allow(clippy::missing_panics_doc, clippy::missing_const_for_fn)]
 | 
					#![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 datapack;
 | 
				
			||||||
pub mod util;
 | 
					pub mod util;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(feature = "zip")]
 | 
					#[cfg(all(feature = "fs_access", feature = "zip"))]
 | 
				
			||||||
use zip::ZipWriter;
 | 
					use zip::ZipWriter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Folder representation in virtual file system
 | 
					/// Folder representation in virtual file system
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue