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,50 +526,67 @@ impl Transpiler {
} }
}, },
} }
(acc_setup, acc_move, statics)}, (require_dyn_params, acc_setup, acc_move, statics)},
); );
let statics_len = static_params.len(); if require_dyn_params {
let joined_statics = let statics_len = static_params.len();
super::util::join_macro_strings(static_params.into_iter().enumerate().map( let joined_statics = super::util::join_macro_strings(
|(i, (k, v))| match v { static_params
MacroString::String(s) => { .into_iter()
let mut s = format!(r#"{k}:"{s}""#); .enumerate()
if i < statics_len - 1 { .map(|(i, (k, v))| match v {
s.push(','); MacroString::String(s) => {
let mut s = format!(r#"{k}:"{s}""#);
if i < statics_len - 1 {
s.push(',');
}
MacroString::String(s)
} }
MacroString::String(s) MacroString::MacroString(mut parts) => {
} parts.insert(
MacroString::MacroString(mut parts) => { 0,
parts.insert(0, MacroStringPart::String(format!(r#"{k}:""#))); MacroStringPart::String(format!(r#"{k}:""#)),
let mut ending = '"'.to_string(); );
if i < statics_len - 1 { let mut ending = '"'.to_string();
ending.push(','); if i < statics_len - 1 {
ending.push(',');
}
parts.push(MacroStringPart::String(ending));
MacroString::MacroString(parts)
} }
parts.push(MacroStringPart::String(ending)); }),
MacroString::MacroString(parts) );
} let storage_suffix = function_location.replace(['/', ':'], "_");
}, let statics_cmd = match joined_statics {
)); MacroString::String(s) => Command::Raw(format!(
let statics_cmd = match joined_statics { r"data merge storage shulkerscript:function_arguments_{storage_suffix} {{{s}}}"
MacroString::String(s) => Command::Raw(format!( )),
r"data merge storage shulkerscript:function_arguments {{{s}}}" MacroString::MacroString(_) => {
)), let prefix = MacroString::String(
MacroString::MacroString(_) => Command::UsesMacro( format!("data merge storage shulkerscript:function_arguments_{storage_suffix} {{"),
super::util::join_macro_strings([ );
MacroString::String( Command::UsesMacro(
"data merge storage shulkerscript:function_arguments {" super::util::join_macro_strings([
.to_string(), prefix,
), 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,48 +703,61 @@ 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 arguments_iter = arguments.iter().map(|(ident, v)| match v {
MacroString::String(s) => MacroString::String(format!(
r#"{macro_name}:"{escaped}""#,
macro_name = crate::util::identifier_to_macro(ident),
escaped = crate::util::escape_str(s)
)),
MacroString::MacroString(parts) => MacroString::MacroString(
std::iter::once(MacroStringPart::String(format!(
r#"{macro_name}:""#,
macro_name = crate::util::identifier_to_macro(ident)
)))
.chain(parts.clone().into_iter().map(|part| match part {
MacroStringPart::String(s) => {
MacroStringPart::String(crate::util::escape_str(&s).to_string())
}
macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage,
}))
.chain(std::iter::once(MacroStringPart::String('"'.to_string())))
.collect(),
),
});
let arguments = super::util::join_macro_strings(arguments_iter);
let cmd = match arguments { let cmd = if arguments.is_empty() {
MacroString::String(arguments) => { Command::Raw(function_call)
write!(function_call, " {{{arguments}}}").unwrap(); } else {
Command::Raw(function_call) let arguments_iter = arguments.iter().map(|(ident, v)| match v {
} MacroString::String(s) => MacroString::String(format!(
MacroString::MacroString(mut parts) => { r#"{macro_name}:"{escaped}""#,
function_call.push_str(" {"); macro_name = crate::util::identifier_to_macro(ident),
parts.insert(0, MacroStringPart::String(function_call)); escaped = crate::util::escape_str(s)
parts.push(MacroStringPart::String('}'.to_string())); )),
Command::UsesMacro(MacroString::MacroString(parts).into()) MacroString::MacroString(parts) => MacroString::MacroString(
std::iter::once(MacroStringPart::String(format!(
r#"{macro_name}:""#,
macro_name = crate::util::identifier_to_macro(ident)
)))
.chain(parts.clone().into_iter().map(|part| match part {
MacroStringPart::String(s) => MacroStringPart::String(
crate::util::escape_str(&s).to_string(),
),
macro_usage @ MacroStringPart::MacroUsage(_) => macro_usage,
}))
.chain(std::iter::once(MacroStringPart::String('"'.to_string())))
.collect(),
),
});
let arguments = super::util::join_macro_strings(arguments_iter);
match arguments {
MacroString::String(arguments) => {
write!(function_call, " {{{arguments}}}").unwrap();
Command::Raw(function_call)
}
MacroString::MacroString(mut parts) => {
function_call.push_str(" {");
parts.insert(0, MacroStringPart::String(function_call));
parts.push(MacroStringPart::String('}'.to_string()));
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)
} }