only use function arg storage if required

This commit is contained in:
Moritz Hölting 2025-08-13 18:05:15 +02:00
parent 0ee456756a
commit 15dde037b7
2 changed files with 115 additions and 80 deletions

View File

@ -32,7 +32,7 @@ use super::{
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum TranspiledFunctionArguments { pub enum TranspiledFunctionArguments {
None, None,
Static(BTreeMap<String, MacroString>), Static(BTreeMap<String, MacroString>, Vec<Command>),
Dynamic(Vec<Command>), Dynamic(Vec<Command>),
} }
@ -430,9 +430,9 @@ impl Transpiler {
} }
if compiled_args.iter().any(|arg| !arg.is_static()) { if compiled_args.iter().any(|arg| !arg.is_static()) {
let (mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold( let (require_dyn_params, mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold(
(Vec::new(), Vec::new(), BTreeMap::new()), (false, Vec::new(), Vec::new(), BTreeMap::new()),
|(mut acc_setup, mut acc_move, mut statics), (param, data)| { |(mut require_dyn_params, mut acc_setup, mut acc_move, mut statics), (param, data)| {
match param.variable_type() { match param.variable_type() {
FunctionVariableType::Macro(_) => { FunctionVariableType::Macro(_) => {
let arg_name = crate::util::identifier_to_macro(param.identifier().span.str()); let arg_name = crate::util::identifier_to_macro(param.identifier().span.str());
@ -455,6 +455,7 @@ impl Transpiler {
}; };
} }
Parameter::Storage { prepare_cmds, storage_name, path } => { Parameter::Storage { prepare_cmds, storage_name, path } => {
require_dyn_params = true;
acc_setup.extend(prepare_cmds); acc_setup.extend(prepare_cmds);
acc_move.push(Command::Raw( acc_move.push(Command::Raw(
format!(r"data modify storage shulkerscript:function_arguments {arg_name} set from storage {storage_name} {path}") format!(r"data modify storage shulkerscript:function_arguments {arg_name} set from storage {storage_name} {path}")
@ -495,6 +496,7 @@ impl Transpiler {
} }
}, },
FunctionVariableType::Boolean(_) => { FunctionVariableType::Boolean(_) => {
require_dyn_params = true;
let target_storage_name = format!("shulkerscript:arguments_{}", function_location.replace(['/', ':'], "_")); let target_storage_name = format!("shulkerscript:arguments_{}", function_location.replace(['/', ':'], "_"));
let param_str = param.identifier().span.str(); let param_str = param.identifier().span.str();
let target_path = crate::util::identifier_to_scoreboard_target(param_str); let target_path = crate::util::identifier_to_scoreboard_target(param_str);
@ -524,12 +526,15 @@ impl Transpiler {
} }
}, },
} }
(acc_setup, acc_move, statics)}, (require_dyn_params, acc_setup, acc_move, statics)},
); );
if require_dyn_params {
let statics_len = static_params.len(); let statics_len = static_params.len();
let joined_statics = let joined_statics = super::util::join_macro_strings(
super::util::join_macro_strings(static_params.into_iter().enumerate().map( static_params
|(i, (k, v))| match v { .into_iter()
.enumerate()
.map(|(i, (k, v))| match v {
MacroString::String(s) => { MacroString::String(s) => {
let mut s = format!(r#"{k}:"{s}""#); let mut s = format!(r#"{k}:"{s}""#);
if i < statics_len - 1 { if i < statics_len - 1 {
@ -538,7 +543,10 @@ impl Transpiler {
MacroString::String(s) MacroString::String(s)
} }
MacroString::MacroString(mut parts) => { MacroString::MacroString(mut parts) => {
parts.insert(0, MacroStringPart::String(format!(r#"{k}:""#))); parts.insert(
0,
MacroStringPart::String(format!(r#"{k}:""#)),
);
let mut ending = '"'.to_string(); let mut ending = '"'.to_string();
if i < statics_len - 1 { if i < statics_len - 1 {
ending.push(','); ending.push(',');
@ -546,28 +554,39 @@ impl Transpiler {
parts.push(MacroStringPart::String(ending)); parts.push(MacroStringPart::String(ending));
MacroString::MacroString(parts) MacroString::MacroString(parts)
} }
}, }),
)); );
let storage_suffix = function_location.replace(['/', ':'], "_");
let statics_cmd = match joined_statics { let statics_cmd = match joined_statics {
MacroString::String(s) => Command::Raw(format!( MacroString::String(s) => Command::Raw(format!(
r"data merge storage shulkerscript:function_arguments {{{s}}}" r"data merge storage shulkerscript:function_arguments_{storage_suffix} {{{s}}}"
)), )),
MacroString::MacroString(_) => Command::UsesMacro( MacroString::MacroString(_) => {
let prefix = MacroString::String(
format!("data merge storage shulkerscript:function_arguments_{storage_suffix} {{"),
);
Command::UsesMacro(
super::util::join_macro_strings([ super::util::join_macro_strings([
MacroString::String( prefix,
"data merge storage shulkerscript:function_arguments {"
.to_string(),
),
joined_statics, joined_statics,
MacroString::String("}".to_string()), MacroString::String("}".to_string()),
]) ])
.into(), .into(),
), )
}
}; };
setup_cmds.push(statics_cmd); setup_cmds.push(statics_cmd);
setup_cmds.extend(move_cmds); setup_cmds.extend(move_cmds);
Ok(TranspiledFunctionArguments::Dynamic(setup_cmds)) Ok(TranspiledFunctionArguments::Dynamic(setup_cmds))
} else {
setup_cmds.extend(move_cmds);
Ok(TranspiledFunctionArguments::Static(
static_params,
setup_cmds,
))
}
} else { } else {
let function_args = parameters let function_args = parameters
.clone() .clone()
@ -579,7 +598,10 @@ impl Transpiler {
) )
.map(|(k, v)| (k.identifier().span.str().to_string(), v)) .map(|(k, v)| (k.identifier().span.str().to_string(), v))
.collect(); .collect();
Ok(TranspiledFunctionArguments::Static(function_args)) Ok(TranspiledFunctionArguments::Static(
function_args,
Vec::new(),
))
} }
} }
_ => Ok(TranspiledFunctionArguments::None), _ => Ok(TranspiledFunctionArguments::None),

View File

@ -703,8 +703,12 @@ impl Transpiler {
)?; )?;
let mut function_call = format!("function {location}"); let mut function_call = format!("function {location}");
match arguments { match arguments {
TranspiledFunctionArguments::Static(arguments) => { TranspiledFunctionArguments::Static(arguments, mut setup_cmds) => {
use std::fmt::Write; use std::fmt::Write;
let cmd = if arguments.is_empty() {
Command::Raw(function_call)
} else {
let arguments_iter = arguments.iter().map(|(ident, v)| match v { let arguments_iter = arguments.iter().map(|(ident, v)| match v {
MacroString::String(s) => MacroString::String(format!( MacroString::String(s) => MacroString::String(format!(
r#"{macro_name}:"{escaped}""#, r#"{macro_name}:"{escaped}""#,
@ -717,9 +721,9 @@ impl Transpiler {
macro_name = crate::util::identifier_to_macro(ident) macro_name = crate::util::identifier_to_macro(ident)
))) )))
.chain(parts.clone().into_iter().map(|part| match part { .chain(parts.clone().into_iter().map(|part| match part {
MacroStringPart::String(s) => { MacroStringPart::String(s) => MacroStringPart::String(
MacroStringPart::String(crate::util::escape_str(&s).to_string()) crate::util::escape_str(&s).to_string(),
} ),
macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage, macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage,
})) }))
.chain(std::iter::once(MacroStringPart::String('"'.to_string()))) .chain(std::iter::once(MacroStringPart::String('"'.to_string())))
@ -728,7 +732,7 @@ impl Transpiler {
}); });
let arguments = super::util::join_macro_strings(arguments_iter); let arguments = super::util::join_macro_strings(arguments_iter);
let cmd = match arguments { match arguments {
MacroString::String(arguments) => { MacroString::String(arguments) => {
write!(function_call, " {{{arguments}}}").unwrap(); write!(function_call, " {{{arguments}}}").unwrap();
Command::Raw(function_call) Command::Raw(function_call)
@ -739,12 +743,21 @@ impl Transpiler {
parts.push(MacroStringPart::String('}'.to_string())); parts.push(MacroStringPart::String('}'.to_string()));
Command::UsesMacro(MacroString::MacroString(parts).into()) Command::UsesMacro(MacroString::MacroString(parts).into())
} }
}
}; };
Ok(vec![cmd]) setup_cmds.push(cmd);
Ok(setup_cmds)
} }
TranspiledFunctionArguments::Dynamic(mut cmds) => { TranspiledFunctionArguments::Dynamic(mut cmds) => {
function_call.push_str(" with storage shulkerscript:function_arguments"); use std::fmt::Write as _;
let _ = write!(
function_call,
" with storage shulkerscript:function_arguments_{suffix}",
suffix = location.replace(['/', ':'], "_")
);
cmds.push(Command::Raw(function_call)); cmds.push(Command::Raw(function_call));
Ok(cmds) Ok(cmds)
} }