pass on macros to group
This commit is contained in:
parent
84ee2a5295
commit
2c9fa613ed
|
@ -1,7 +1,11 @@
|
||||||
//! Represents a command that can be included in a function.
|
//! Represents a command that can be included in a function.
|
||||||
|
|
||||||
mod execute;
|
mod execute;
|
||||||
use std::{collections::HashMap, ops::RangeInclusive, sync::OnceLock};
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
ops::RangeInclusive,
|
||||||
|
sync::OnceLock,
|
||||||
|
};
|
||||||
|
|
||||||
pub use execute::{Condition, Execute};
|
pub use execute::{Condition, Execute};
|
||||||
|
|
||||||
|
@ -10,7 +14,10 @@ use chksum_md5 as md5;
|
||||||
use super::Function;
|
use super::Function;
|
||||||
use crate::{
|
use crate::{
|
||||||
prelude::Datapack,
|
prelude::Datapack,
|
||||||
util::{compile::{CompileOptions, FunctionCompilerState, MutCompilerState}, MacroString},
|
util::{
|
||||||
|
compile::{CompileOptions, FunctionCompilerState, MutCompilerState},
|
||||||
|
MacroString,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents a command that can be included in a function.
|
/// Represents a command that can be included in a function.
|
||||||
|
@ -47,7 +54,7 @@ impl Command {
|
||||||
) -> Vec<String> {
|
) -> Vec<String> {
|
||||||
match self {
|
match self {
|
||||||
Self::Raw(command) => vec![command.clone()],
|
Self::Raw(command) => vec![command.clone()],
|
||||||
Self::UsesMacro(command) => vec![compile_macro(command)],
|
Self::UsesMacro(command) => vec![command.compile()],
|
||||||
Self::Debug(message) => compile_debug(message, options),
|
Self::Debug(message) => compile_debug(message, options),
|
||||||
Self::Execute(ex) => ex.compile(options, global_state, function_state),
|
Self::Execute(ex) => ex.compile(options, global_state, function_state),
|
||||||
Self::Group(commands) => compile_group(commands, options, global_state, function_state),
|
Self::Group(commands) => compile_group(commands, options, global_state, function_state),
|
||||||
|
@ -79,6 +86,26 @@ impl Command {
|
||||||
Self::Execute(ex) => ex.validate(pack_formats),
|
Self::Execute(ex) => ex.validate(pack_formats),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether the command contains a macro.
|
||||||
|
#[must_use]
|
||||||
|
pub fn contains_macro(&self, options: &CompileOptions) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Raw(_) | Self::Comment(_) | Self::Debug(_) | Self::Execute(_) => false,
|
||||||
|
Self::UsesMacro(cmd) => cmd.contains_macro(),
|
||||||
|
Self::Group(commands) => group_contains_macro(commands, options),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the names of the macros used
|
||||||
|
#[must_use]
|
||||||
|
pub fn get_macros(&self) -> HashSet<&str> {
|
||||||
|
match self {
|
||||||
|
Self::Raw(_) | Self::Comment(_) | Self::Debug(_) | Self::Execute(_) => HashSet::new(),
|
||||||
|
Self::UsesMacro(cmd) => cmd.get_macros(),
|
||||||
|
Self::Group(commands) => group_get_macros(commands),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Command {
|
impl From<&str> for Command {
|
||||||
|
@ -108,14 +135,6 @@ fn compile_debug(message: &str, option: &CompileOptions) -> Vec<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_macro(command: &MacroString) -> String {
|
|
||||||
if command.contains_macro() {
|
|
||||||
format!("${}", command.compile())
|
|
||||||
} else {
|
|
||||||
command.compile()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument(skip_all, fields(commands = ?commands))]
|
#[tracing::instrument(skip_all, fields(commands = ?commands))]
|
||||||
fn compile_group(
|
fn compile_group(
|
||||||
commands: &[Command],
|
commands: &[Command],
|
||||||
|
@ -130,6 +149,7 @@ fn compile_group(
|
||||||
// only create a function if there are more than one command
|
// only create a function if there are more than one command
|
||||||
if command_count > 1 {
|
if command_count > 1 {
|
||||||
let uid = function_state.request_uid();
|
let uid = function_state.request_uid();
|
||||||
|
let pass_macros = group_contains_macro(commands, options);
|
||||||
|
|
||||||
// calculate a hashed path for the function in the `sb` subfolder
|
// calculate a hashed path for the function in the `sb` subfolder
|
||||||
let function_path = {
|
let function_path = {
|
||||||
|
@ -149,7 +169,22 @@ fn compile_group(
|
||||||
function.get_commands_mut().extend(commands.iter().cloned());
|
function.get_commands_mut().extend(commands.iter().cloned());
|
||||||
function_state.add_function(&function_path, function);
|
function_state.add_function(&function_path, function);
|
||||||
|
|
||||||
vec![format!("function {namespace}:{function_path}")]
|
let mut function_invocation = format!("function {namespace}:{function_path}");
|
||||||
|
|
||||||
|
if pass_macros {
|
||||||
|
let macros_block =
|
||||||
|
group_get_macros(commands)
|
||||||
|
.into_iter()
|
||||||
|
.fold(String::new(), |mut s, m| {
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
write!(&mut s, "{m}:$({m})").expect("can always write to string");
|
||||||
|
s
|
||||||
|
});
|
||||||
|
function_invocation.push_str(&format!(" {{{macros_block}}}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec![function_invocation]
|
||||||
} else {
|
} else {
|
||||||
commands
|
commands
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -158,6 +193,18 @@ fn compile_group(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn group_contains_macro(commands: &[Command], options: &CompileOptions) -> bool {
|
||||||
|
commands.iter().any(|cmd| cmd.contains_macro(options))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_get_macros(commands: &[Command]) -> HashSet<&str> {
|
||||||
|
let mut macros = HashSet::new();
|
||||||
|
for cmd in commands {
|
||||||
|
macros.extend(cmd.get_macros());
|
||||||
|
}
|
||||||
|
macros
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
fn validate_raw_cmd(cmd: &str, pack_formats: &RangeInclusive<u8>) -> bool {
|
fn validate_raw_cmd(cmd: &str, pack_formats: &RangeInclusive<u8>) -> bool {
|
||||||
static CMD_FORMATS: OnceLock<HashMap<&str, RangeInclusive<u8>>> = OnceLock::new();
|
static CMD_FORMATS: OnceLock<HashMap<&str, RangeInclusive<u8>>> = OnceLock::new();
|
||||||
|
|
|
@ -62,7 +62,15 @@ impl Function {
|
||||||
let content = self
|
let content = self
|
||||||
.commands
|
.commands
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|c| c.compile(options, global_state, function_state))
|
.flat_map(|c| {
|
||||||
|
let cmds = c.compile(options, global_state, function_state);
|
||||||
|
|
||||||
|
if c.contains_macro(options) {
|
||||||
|
cmds.into_iter().map(|c| format!("${c}")).collect()
|
||||||
|
} else {
|
||||||
|
cmds
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
VFile::Text(content)
|
VFile::Text(content)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(clippy::module_name_repetitions)]
|
#![allow(clippy::module_name_repetitions)]
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::{borrow::Cow, collections::HashSet};
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -64,6 +64,21 @@ impl MacroString {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the names of the macros used in the [`MacroString`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn get_macros(&self) -> HashSet<&str> {
|
||||||
|
match self {
|
||||||
|
Self::String(_) => HashSet::new(),
|
||||||
|
Self::MacroString(parts) => parts
|
||||||
|
.iter()
|
||||||
|
.filter_map(|p| match p {
|
||||||
|
MacroStringPart::String(_) => None,
|
||||||
|
MacroStringPart::MacroUsage(m) => Some(m.as_str()),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for MacroString {
|
impl From<String> for MacroString {
|
||||||
|
|
Loading…
Reference in New Issue