remove duplicate function, optimize function calls with mixed static and dynamic parameters

This commit is contained in:
Moritz Hölting 2025-03-13 14:35:59 +01:00
parent cebe3e9cb0
commit 863bc784cc
4 changed files with 328 additions and 319 deletions

View File

@ -34,6 +34,7 @@ use crate::{
}, },
}; };
// TODO: fix this leading to compile errors without 'shulkerbox' feature
/// Compile-time evaluated value /// Compile-time evaluated value
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -419,24 +420,26 @@ impl Binary {
let right = self.right_operand().comptime_eval(scope, handler)?; let right = self.right_operand().comptime_eval(scope, handler)?;
match (left, right) { match (left, right) {
(ComptimeValue::Boolean(true), _) | (_, ComptimeValue::Boolean(true)) if matches!(self.operator(), BinaryOperator::LogicalOr(..)) (ComptimeValue::Boolean(true), _) | (_, ComptimeValue::Boolean(true))
// TODO: re-enable if can_yield_type works properly if matches!(self.operator(), BinaryOperator::LogicalOr(..))
/*&& self && self
.left_operand() .left_operand()
.can_yield_type(ValueType::Boolean, scope) .can_yield_type(ValueType::Boolean, scope)
&& self && self
.right_operand() .right_operand()
.can_yield_type(ValueType::Boolean, scope)*/ => { .can_yield_type(ValueType::Boolean, scope) =>
{
Some(ComptimeValue::Boolean(true)) Some(ComptimeValue::Boolean(true))
} }
(ComptimeValue::Boolean(false), _) | (_, ComptimeValue::Boolean(false)) if matches!(self.operator(), BinaryOperator::LogicalAnd(..)) (ComptimeValue::Boolean(false), _) | (_, ComptimeValue::Boolean(false))
// TODO: re-enable if can_yield_type works properly if matches!(self.operator(), BinaryOperator::LogicalAnd(..))
/*&& self && self
.left_operand() .left_operand()
.can_yield_type(ValueType::Boolean, scope) .can_yield_type(ValueType::Boolean, scope)
&& self && self
.right_operand() .right_operand()
.can_yield_type(ValueType::Boolean, scope)*/ => { .can_yield_type(ValueType::Boolean, scope) =>
{
Some(ComptimeValue::Boolean(false)) Some(ComptimeValue::Boolean(false))
} }
(ComptimeValue::Boolean(left), ComptimeValue::Boolean(right)) => { (ComptimeValue::Boolean(left), ComptimeValue::Boolean(right)) => {
@ -660,7 +663,7 @@ impl Transpiler {
target: score_target, target: score_target,
} => { } => {
let mut expr_cmds = self.transpile_primary_expression( let mut expr_cmds = self.transpile_primary_expression(
dbg!(prefix).operand(), prefix.operand(),
target, target,
scope, scope,
handler, handler,
@ -711,18 +714,15 @@ impl Transpiler {
_ => { _ => {
let err = TranspileError::MismatchedTypes(MismatchedTypes { let err = TranspileError::MismatchedTypes(MismatchedTypes {
expression: prefix.span(), expression: prefix.span(),
expected_type: ExpectedType::Integer, expected_type: target.value_type().into(),
}); });
handler.receive(err.clone()); handler.receive(err.clone());
Err(err) Err(err)
} }
}, },
PrefixOperator::LogicalNot(_) => { PrefixOperator::LogicalNot(_) => {
let (mut cmds, cond) = self let (mut cmds, cond) =
.transpile_primary_expression_as_condition(primary, scope, handler) self.transpile_primary_expression_as_condition(primary, scope, handler)?;
.inspect_err(|err| {
dbg!(err);
})?;
let store_cmds = let store_cmds =
self.store_condition_success(cond, target, primary, handler)?; self.store_condition_success(cond, target, primary, handler)?;
@ -864,7 +864,7 @@ impl Transpiler {
handler: &impl Handler<base::Error>, handler: &impl Handler<base::Error>,
) -> TranspileResult<Vec<Command>> { ) -> TranspileResult<Vec<Command>> {
if let Some(value) = binary.comptime_eval(scope, handler) { if let Some(value) = binary.comptime_eval(scope, handler) {
self.transpile_comptime_value(&value, binary, target, scope, handler) self.store_comptime_value(&value, target, binary, handler)
} else { } else {
match binary.operator() { match binary.operator() {
BinaryOperator::Add(_) BinaryOperator::Add(_)
@ -977,12 +977,12 @@ impl Transpiler {
format!("data storage {storage_name} {{{path}: 1b}}").into(), format!("data storage {storage_name} {{{path}: 1b}}").into(),
)), )),
)), )),
VariableData::FunctionArgument { .. } => Ok(( VariableData::MacroParameter { macro_name, .. } => Ok((
Vec::new(), Vec::new(),
ExtendedCondition::Runtime(Condition::Atom( ExtendedCondition::Runtime(Condition::Atom(
shulkerbox::util::MacroString::MacroString(vec![ shulkerbox::util::MacroString::MacroString(vec![
shulkerbox::util::MacroStringPart::MacroUsage( shulkerbox::util::MacroStringPart::MacroUsage(
ident.span.str().to_string(), macro_name.clone(),
), ),
]), ]),
)), )),
@ -1306,13 +1306,11 @@ impl Transpiler {
} }
} }
#[expect(clippy::unused_self)] fn store_comptime_value(
fn transpile_comptime_value( &mut self,
&self,
value: &ComptimeValue, value: &ComptimeValue,
original: &impl SourceElement,
target: &DataLocation, target: &DataLocation,
_scope: &Arc<super::Scope>, source: &impl SourceElement,
handler: &impl Handler<base::Error>, handler: &impl Handler<base::Error>,
) -> TranspileResult<Vec<Command>> { ) -> TranspileResult<Vec<Command>> {
match value { match value {
@ -1323,7 +1321,7 @@ impl Transpiler {
DataLocation::Tag { .. } => { DataLocation::Tag { .. } => {
let err = TranspileError::MismatchedTypes(MismatchedTypes { let err = TranspileError::MismatchedTypes(MismatchedTypes {
expected_type: ExpectedType::Boolean, expected_type: ExpectedType::Boolean,
expression: original.span(), expression: source.span(),
}); });
handler.receive(err.clone()); handler.receive(err.clone());
Err(err) Err(err)
@ -1346,7 +1344,7 @@ impl Transpiler {
))]) ))])
} else { } else {
let err = TranspileError::MismatchedTypes(MismatchedTypes { let err = TranspileError::MismatchedTypes(MismatchedTypes {
expression: original.span(), expression: source.span(),
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
}); });
handler.receive(err.clone()); handler.receive(err.clone());
@ -1355,12 +1353,6 @@ impl Transpiler {
} }
}, },
&ComptimeValue::Boolean(value) => match target { &ComptimeValue::Boolean(value) => match target {
DataLocation::ScoreboardValue { objective, target } => {
Ok(vec![Command::Raw(format!(
"scoreboard players set {target} {objective} {value}",
value = u8::from(value)
))])
}
DataLocation::Tag { tag_name, entity } => Ok(vec![Command::Raw(format!( DataLocation::Tag { tag_name, entity } => Ok(vec![Command::Raw(format!(
"tag {entity} {op} {tag_name}", "tag {entity} {op} {tag_name}",
op = if value { "add" } else { "remove" } op = if value { "add" } else { "remove" }
@ -1378,111 +1370,48 @@ impl Transpiler {
))]) ))])
} else { } else {
let err = TranspileError::MismatchedTypes(MismatchedTypes { let err = TranspileError::MismatchedTypes(MismatchedTypes {
expression: original.span(), expression: source.span(),
expected_type: target.value_type().into(), expected_type: target.value_type().into(),
}); });
handler.receive(err.clone()); handler.receive(err.clone());
Err(err) Err(err)
} }
} }
},
ComptimeValue::String(_) | ComptimeValue::MacroString(_) => {
let err = TranspileError::MismatchedTypes(MismatchedTypes {
expected_type: target.value_type().into(),
expression: original.span(),
});
handler.receive(err.clone());
Err(err)
}
}
}
#[expect(clippy::needless_pass_by_ref_mut)]
fn store_comptime_value(
&mut self,
value: &ComptimeValue,
target: &DataLocation,
source: &impl SourceElement,
handler: &impl Handler<base::Error>,
) -> TranspileResult<Vec<Command>> {
match value {
ComptimeValue::Integer(int) => match target {
DataLocation::ScoreboardValue { objective, target } => Ok(vec![Command::Raw(
format!("scoreboard players set {target} {objective} {int}"),
)]),
DataLocation::Tag { .. } => {
let err = TranspileError::MismatchedTypes(MismatchedTypes {
expected_type: ExpectedType::Boolean,
expression: source.span(),
});
handler.receive(err.clone());
Err(err)
}
DataLocation::Storage {
storage_name,
path,
r#type,
} => {
if matches!(
r#type,
StorageType::Byte
| StorageType::Double
| StorageType::Int
| StorageType::Long
) {
Ok(vec![Command::Raw(format!(
"data modify storage {storage} {path} set value {value}{suffix}",
storage = storage_name,
path = path,
value = int,
suffix = r#type.suffix()
))])
} else {
let err = TranspileError::MismatchedTypes(MismatchedTypes {
expression: source.span(),
expected_type: ExpectedType::Integer,
});
handler.receive(err.clone());
Err(err)
}
}
},
&ComptimeValue::Boolean(boolean) => match target {
DataLocation::Tag { tag_name, entity } => {
let cmd = format!(
"tag {target} {op} {tag}",
target = entity,
op = if boolean { "add" } else { "remove" },
tag = tag_name
);
Ok(vec![shulkerbox::prelude::Command::Raw(cmd)])
}
DataLocation::Storage {
storage_name,
path,
r#type,
} => {
let cmd = format!(
"data modify storage {storage} {path} set value {value}{suffix}",
storage = storage_name,
path = path,
value = if boolean { "1" } else { "0" },
suffix = r#type.suffix()
);
Ok(vec![shulkerbox::prelude::Command::Raw(cmd)])
}
DataLocation::ScoreboardValue { objective, target } => { DataLocation::ScoreboardValue { objective, target } => {
let cmd = format!( Ok(vec![Command::Raw(format!(
"scoreboard players set {target} {objective} {value}", "scoreboard players set {target} {objective} {value}",
target = target, value = u8::from(value)
objective = objective, ))])
value = if boolean { "1" } else { "0" }
);
Ok(vec![shulkerbox::prelude::Command::Raw(cmd)])
} }
}, },
ComptimeValue::String(_) | ComptimeValue::MacroString(_) => { ComptimeValue::String(value) => self.store_comptime_value(
todo!("store string comptime value") &ComptimeValue::MacroString(value.clone().into()),
target,
source,
handler,
),
ComptimeValue::MacroString(value) => {
match target {
DataLocation::Storage {
r#type: StorageType::Boolean,
..
}
| DataLocation::Tag { .. } => self.store_condition_success(
ExtendedCondition::Runtime(Condition::Atom(value.clone())),
target,
source,
handler,
),
// DataLocation::Storage { storage_name, path, r#type: StorageType::String } => todo!("implement storage string")
_ => {
let err = TranspileError::MismatchedTypes(MismatchedTypes {
expected_type: target.value_type().into(),
expression: source.span(),
});
handler.receive(err.clone());
Err(err)
}
}
} }
} }
} }

View File

@ -268,7 +268,6 @@ impl Transpiler {
/// Gets the function at the given path, or transpiles it if it hasn't been transpiled yet. /// Gets the function at the given path, or transpiles it if it hasn't been transpiled yet.
/// Returns the location of the function or None if the function does not exist. /// Returns the location of the function or None if the function does not exist.
#[allow(clippy::significant_drop_tightening)]
#[tracing::instrument(level = "trace", skip(self, handler))] #[tracing::instrument(level = "trace", skip(self, handler))]
pub(super) fn get_or_transpile_function( pub(super) fn get_or_transpile_function(
&mut self, &mut self,
@ -324,7 +323,13 @@ impl Transpiler {
let function_scope = Scope::with_parent(scope); let function_scope = Scope::with_parent(scope);
for (i, param) in function_data.parameters.iter().enumerate() { for (i, param) in function_data.parameters.iter().enumerate() {
function_scope.set_variable(param, VariableData::FunctionArgument { index: i }); function_scope.set_variable(
param,
VariableData::MacroParameter {
index: i,
macro_name: crate::util::identifier_to_macro(param).to_string(),
},
);
} }
let statements = function_data.statements.clone(); let statements = function_data.statements.clone();
@ -468,12 +473,9 @@ impl Transpiler {
err err
})?; })?;
match var.as_ref() { match var.as_ref() {
VariableData::FunctionArgument { .. } => { VariableData::MacroParameter { macro_name, .. } => {
Ok(Parameter::Static(MacroString::MacroString(vec![ Ok(Parameter::Static(MacroString::MacroString(vec![
MacroStringPart::MacroUsage( MacroStringPart::MacroUsage(macro_name.clone()),
crate::util::identifier_to_macro(ident.span.str())
.to_string(),
),
]))) ])))
} }
@ -486,14 +488,22 @@ impl Transpiler {
&super::expression::DataLocation::Storage { &super::expression::DataLocation::Storage {
storage_name: temp_storage.clone(), storage_name: temp_storage.clone(),
path: temp_path[0].clone(), path: temp_path[0].clone(),
r#type: StorageType::Int, r#type: match var.as_ref() {
VariableData::BooleanStorage { .. } => {
StorageType::Boolean
}
VariableData::ScoreboardValue { .. } => {
StorageType::Int
}
_ => unreachable!("checked in parent match"),
},
}, },
scope, scope,
handler, handler,
)?; )?;
Ok(Parameter::Dynamic { Ok(Parameter::Dynamic {
prepare_cmds: dbg!(prepare_cmds), prepare_cmds,
storage_name: temp_storage, storage_name: temp_storage,
path: std::mem::take(&mut temp_path[0]), path: std::mem::take(&mut temp_path[0]),
}) })
@ -542,30 +552,70 @@ impl Transpiler {
return Err(err.clone()); return Err(err.clone());
} }
if compiled_args.iter().any(|arg| !arg.is_static()) { if compiled_args.iter().any(|arg| !arg.is_static()) {
let (mut setup_cmds, move_cmds) = parameters.clone().into_iter().zip(compiled_args).fold( let (mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold(
(Vec::new(), Vec::new()), (Vec::new(), Vec::new(), BTreeMap::new()),
|(mut acc_setup, mut acc_move), (arg_name, data)| { |(mut acc_setup, mut acc_move, mut statics), (arg_name, data)| {
let arg_name = crate::util::identifier_to_macro(&arg_name); let arg_name = crate::util::identifier_to_macro(&arg_name);
match data { match data {
Parameter::Static(s) => { Parameter::Static(s) => {
// TODO: optimize by combining into single `data merge` command match s {
let move_cmd = match s { MacroString::String(value) => statics.insert(arg_name.to_string(), MacroString::String(crate::util::escape_str(&value).to_string())),
MacroString::String(value) => Command::Raw(format!(r#"data modify storage shulkerscript:function_arguments {arg_name} set value "{value}""#, value = crate::util::escape_str(&value))), MacroString::MacroString(parts) => {
MacroString::MacroString(mut parts) => { let parts = parts.into_iter().map(|part| {
parts.insert(0, MacroStringPart::String(format!(r#"data modify storage shulkerscript:function_arguments {arg_name} set value ""#))); match part {
parts.push(MacroStringPart::String('"'.to_string())); MacroStringPart::String(s) => MacroStringPart::String(crate::util::escape_str(&s).to_string()),
Command::UsesMacro(MacroString::MacroString(parts)) MacroStringPart::MacroUsage(m) => MacroStringPart::MacroUsage(m),
}
}).collect();
statics.insert(arg_name.to_string(), MacroString::MacroString(parts))
} }
}; };
acc_move.push(move_cmd);
} }
Parameter::Dynamic { prepare_cmds, storage_name, path } => { Parameter::Dynamic { prepare_cmds, storage_name, path } => {
acc_setup.extend(prepare_cmds); acc_setup.extend(prepare_cmds);
acc_move.push(Command::Raw(format!(r#"data modify storage shulkerscript:function_arguments {arg_name} set from storage {storage_name} {path}"#))); acc_move.push(Command::Raw(format!(r#"data modify storage shulkerscript:function_arguments {arg_name} set from storage {storage_name} {path}"#)));
} }
} }
(acc_setup, acc_move)}, (acc_setup, acc_move, statics)},
); );
let statics_len = static_params.len();
let joined_statics =
super::util::join_macro_strings(static_params.into_iter().enumerate().map(
|(i, (k, v))| match v {
MacroString::String(s) => {
let mut s = format!(r#"{k}:"{s}""#);
if i < statics_len - 1 {
s.push(',');
}
MacroString::String(s)
}
MacroString::MacroString(mut parts) => {
parts.insert(0, MacroStringPart::String(format!(r#"{k}:""#)));
let mut ending = '"'.to_string();
if i < statics_len - 1 {
ending.push(',');
}
parts.push(MacroStringPart::String(ending));
MacroString::MacroString(parts)
}
},
));
let statics_cmd = match joined_statics {
MacroString::String(s) => Command::Raw(format!(
r#"data merge storage shulkerscript:function_arguments {{{s}}}"#
)),
MacroString::MacroString(_) => {
Command::UsesMacro(super::util::join_macro_strings([
MacroString::String(
"data merge storage shulkerscript:function_arguments {"
.to_string(),
),
joined_statics,
MacroString::String("}".to_string()),
]))
}
};
setup_cmds.push(statics_cmd);
setup_cmds.extend(move_cmds); setup_cmds.extend(move_cmds);
Ok(( Ok((
@ -756,7 +806,14 @@ impl Transpiler {
Expression::Binary(bin) => match bin.comptime_eval(scope, handler) { Expression::Binary(bin) => match bin.comptime_eval(scope, handler) {
Some(ComptimeValue::String(cmd)) => Ok(vec![Command::Raw(cmd)]), Some(ComptimeValue::String(cmd)) => Ok(vec![Command::Raw(cmd)]),
Some(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd)]), Some(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd)]),
_ => todo!("run binary expression"), _ => {
let err = TranspileError::MismatchedTypes(MismatchedTypes {
expression: bin.span(),
expected_type: ExpectedType::String,
});
handler.receive(err.clone());
Err(err)
}
}, },
} }
} }
@ -781,9 +838,7 @@ impl Transpiler {
match arguments { match arguments {
TranspiledFunctionArguments::Static(arguments) => { TranspiledFunctionArguments::Static(arguments) => {
use std::fmt::Write; use std::fmt::Write;
let arguments = arguments let arguments_iter = arguments.iter().map(|(ident, v)| match v {
.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}""#,
macro_name = crate::util::identifier_to_macro(ident), macro_name = crate::util::identifier_to_macro(ident),
@ -803,30 +858,8 @@ impl Transpiler {
.chain(std::iter::once(MacroStringPart::String('"'.to_string()))) .chain(std::iter::once(MacroStringPart::String('"'.to_string())))
.collect(), .collect(),
), ),
})
.fold(MacroString::String(String::new()), |acc, cur| match acc {
MacroString::String(mut s) => match cur {
MacroString::String(cur) => {
s.push_str(&cur);
MacroString::String(s)
}
MacroString::MacroString(cur) => {
let mut parts = vec![MacroStringPart::String(s)];
parts.extend(cur);
MacroString::MacroString(parts)
}
},
MacroString::MacroString(mut parts) => match cur {
MacroString::String(cur) => {
parts.push(MacroStringPart::String(cur));
MacroString::MacroString(parts)
}
MacroString::MacroString(cur) => {
parts.extend(cur);
MacroString::MacroString(parts)
}
},
}); });
let arguments = super::util::join_macro_strings(arguments_iter);
let cmd = match arguments { let cmd = match arguments {
MacroString::String(arguments) => { MacroString::String(arguments) => {

View File

@ -1,5 +1,7 @@
//! Utility methods for transpiling //! Utility methods for transpiling
use shulkerbox::util::{MacroString, MacroStringPart};
fn normalize_program_identifier<S>(identifier: S) -> String fn normalize_program_identifier<S>(identifier: S) -> String
where where
S: AsRef<str>, S: AsRef<str>,
@ -36,3 +38,36 @@ where
normalize_program_identifier(identifier_elements.join("/") + "/" + import_path.as_ref()) normalize_program_identifier(identifier_elements.join("/") + "/" + import_path.as_ref())
} }
} }
/// Join multiple macro strings into one
#[must_use]
pub fn join_macro_strings<I>(strings: I) -> MacroString
where
I: IntoIterator<Item = MacroString>,
{
strings
.into_iter()
.fold(MacroString::String(String::new()), |acc, cur| match acc {
MacroString::String(mut s) => match cur {
MacroString::String(cur) => {
s.push_str(&cur);
MacroString::String(s)
}
MacroString::MacroString(cur) => {
let mut parts = vec![MacroStringPart::String(s)];
parts.extend(cur);
MacroString::MacroString(parts)
}
},
MacroString::MacroString(mut parts) => match cur {
MacroString::String(cur) => {
parts.push(MacroStringPart::String(cur));
MacroString::MacroString(parts)
}
MacroString::MacroString(cur) => {
parts.extend(cur);
MacroString::MacroString(parts)
}
},
})
}

View File

@ -42,10 +42,12 @@ pub enum VariableData {
/// The path to the function once it is generated. /// The path to the function once it is generated.
path: OnceLock<String>, path: OnceLock<String>,
}, },
/// A function argument/parameter. /// A macro function parameter.
FunctionArgument { MacroParameter {
/// The index of the argument. /// The index of the parameter.
index: usize, index: usize,
/// The macro name.
macro_name: String,
}, },
/// A scoreboard. /// A scoreboard.
Scoreboard { Scoreboard {
@ -214,7 +216,7 @@ impl Transpiler {
scope, scope,
handler, handler,
), ),
_ => todo!("declarations not supported yet: {declaration:?}"), _ => todo!("declarations other than single not supported yet: {declaration:?}"),
} }
} }
@ -243,7 +245,7 @@ impl Transpiler {
return Err(error); return Err(error);
} }
let (name, target) = let (name, target) =
get_single_data_location_identifiers(single, program_identifier, scope, handler)?; self.get_single_data_location_identifiers(single, program_identifier, scope, handler)?;
match variable_type { match variable_type {
KeywordKind::Int => { KeywordKind::Int => {
@ -305,7 +307,7 @@ impl Transpiler {
target: target.to_owned(), target: target.to_owned(),
}) })
} }
VariableData::Function { .. } | VariableData::FunctionArgument { .. } => { VariableData::Function { .. } | VariableData::MacroParameter { .. } => {
let err = TranspileError::AssignmentError(AssignmentError { let err = TranspileError::AssignmentError(AssignmentError {
identifier: identifier.span(), identifier: identifier.span(),
message: format!( message: format!(
@ -332,11 +334,11 @@ impl Transpiler {
Err(err) Err(err)
} }
} }
}
#[expect(clippy::too_many_lines)] #[expect(clippy::too_many_lines)]
#[cfg(feature = "shulkerbox")] #[cfg(feature = "shulkerbox")]
fn get_single_data_location_identifiers( fn get_single_data_location_identifiers(
&mut self,
single: &SingleVariableDeclaration, single: &SingleVariableDeclaration,
program_identifier: &str, program_identifier: &str,
scope: &Arc<Scope>, scope: &Arc<Scope>,
@ -365,7 +367,8 @@ fn get_single_data_location_identifiers(
if let TranspileAnnotationValue::Map(map) = deobfuscate_annotation_value { if let TranspileAnnotationValue::Map(map) = deobfuscate_annotation_value {
if map.len() > 2 { if map.len() > 2 {
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation must have at most 2 key-value pairs." message: "Deobfuscate annotation must have at most 2 key-value pairs."
.to_string(), .to_string(),
@ -422,9 +425,11 @@ fn get_single_data_location_identifiers(
Err(error) Err(error)
} }
} else { } else {
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent { let error =
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
annotation: deobfuscate_annotation.span(), annotation: deobfuscate_annotation.span(),
message: "Deobfuscate annotation must have both 'name' and 'target' keys." message:
"Deobfuscate annotation must have both 'name' and 'target' keys."
.to_string(), .to_string(),
}); });
handler.receive(error.clone()); handler.receive(error.clone());
@ -440,12 +445,18 @@ fn get_single_data_location_identifiers(
} }
} else { } else {
let hashed = md5::hash(program_identifier).to_hex_lowercase(); let hashed = md5::hash(program_identifier).to_hex_lowercase();
let name = "shu_values_".to_string() + &hashed; let name = if matches!(variable_type, KeywordKind::Int) {
"shu_values_"
} else {
"shulkerbox:values_"
}
.to_string()
+ &hashed;
let identifier_name = single.identifier().span.str(); let identifier_name = single.identifier().span.str();
// TODO: generate same name each time (not dependent on pointer) let scope_ident = self.temp_counter;
self.temp_counter = self.temp_counter.wrapping_add(1);
let mut target = md5::hash(format!( let mut target = md5::hash(format!(
"{scope}\0{identifier_name}\0{shadowed}", "{scope_ident}\0{identifier_name}\0{shadowed}",
scope = Arc::as_ptr(scope) as usize,
shadowed = scope.get_variable_shadow_count(identifier_name) shadowed = scope.get_variable_shadow_count(identifier_name)
)) ))
.to_hex_lowercase(); .to_hex_lowercase();
@ -457,6 +468,7 @@ fn get_single_data_location_identifiers(
Ok((name, target)) Ok((name, target))
} }
} }
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {