implement tag and array variables
This commit is contained in:
parent
b119ca33c7
commit
237207a447
|
@ -572,7 +572,7 @@ pub struct ScoreVariableDeclaration {
|
|||
close_bracket: Punctuation,
|
||||
/// The optional assignment of the variable.
|
||||
#[get = "pub"]
|
||||
target_assignment: Option<(AnyStringLiteral, VariableDeclarationAssignment)>,
|
||||
assignment: Option<VariableDeclarationAssignment>,
|
||||
/// The annotations of the variable declaration.
|
||||
#[get = "pub"]
|
||||
annotations: VecDeque<Annotation>,
|
||||
|
@ -582,17 +582,18 @@ impl SourceElement for ScoreVariableDeclaration {
|
|||
fn span(&self) -> Span {
|
||||
self.int_keyword
|
||||
.span()
|
||||
.join(&self.target_assignment.as_ref().map_or_else(
|
||||
|| self.close_bracket.span(),
|
||||
|(_, assignment)| assignment.span(),
|
||||
))
|
||||
.join(
|
||||
&self
|
||||
.assignment
|
||||
.as_ref()
|
||||
.map_or_else(|| self.close_bracket.span(), SourceElement::span),
|
||||
)
|
||||
.expect("The span of the score variable declaration is invalid.")
|
||||
}
|
||||
}
|
||||
|
||||
impl ScoreVariableDeclaration {
|
||||
/// Dissolves the [`ScoreVariableDeclaration`] into its components.
|
||||
#[expect(clippy::type_complexity)]
|
||||
#[must_use]
|
||||
pub fn dissolve(
|
||||
self,
|
||||
|
@ -602,7 +603,7 @@ impl ScoreVariableDeclaration {
|
|||
Identifier,
|
||||
Punctuation,
|
||||
Punctuation,
|
||||
Option<(AnyStringLiteral, VariableDeclarationAssignment)>,
|
||||
Option<VariableDeclarationAssignment>,
|
||||
) {
|
||||
(
|
||||
self.int_keyword,
|
||||
|
@ -610,7 +611,7 @@ impl ScoreVariableDeclaration {
|
|||
self.identifier,
|
||||
self.open_bracket,
|
||||
self.close_bracket,
|
||||
self.target_assignment,
|
||||
self.assignment,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -939,9 +940,9 @@ impl<'a> Parser<'a> {
|
|||
&mut self,
|
||||
handler: &impl Handler<base::Error>,
|
||||
) -> ParseResult<VariableDeclaration> {
|
||||
#[derive(Debug, Clone)]
|
||||
enum IndexingType {
|
||||
IntegerSize(Integer),
|
||||
AnyString(AnyStringLiteral),
|
||||
None,
|
||||
}
|
||||
|
||||
|
@ -992,27 +993,13 @@ impl<'a> Parser<'a> {
|
|||
IndexingType::IntegerSize(int)
|
||||
}
|
||||
|
||||
Reading::Atomic(Token::StringLiteral(s)) => {
|
||||
let selector = AnyStringLiteral::from(s);
|
||||
p.forward();
|
||||
IndexingType::AnyString(selector)
|
||||
}
|
||||
Reading::Atomic(Token::MacroStringLiteral(s)) => {
|
||||
let selector = AnyStringLiteral::from(s);
|
||||
p.forward();
|
||||
IndexingType::AnyString(selector)
|
||||
}
|
||||
|
||||
Reading::DelimitedEnd(punc) if punc.punctuation == ']' => {
|
||||
IndexingType::None
|
||||
}
|
||||
|
||||
unexpected => {
|
||||
let err = Error::UnexpectedSyntax(UnexpectedSyntax {
|
||||
expected: SyntaxKind::Either(&[
|
||||
SyntaxKind::Integer,
|
||||
SyntaxKind::AnyStringLiteral,
|
||||
]),
|
||||
expected: SyntaxKind::Integer,
|
||||
found: unexpected.into_token(),
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
|
@ -1034,10 +1021,10 @@ impl<'a> Parser<'a> {
|
|||
let assignment = self
|
||||
.try_parse(|p| {
|
||||
// read equals sign
|
||||
let equals = p.parse_punctuation('=', true, handler)?;
|
||||
let equals = p.parse_punctuation('=', true, &VoidHandler)?;
|
||||
|
||||
// read expression
|
||||
let expression = p.parse_expression(handler)?;
|
||||
let expression = p.parse_expression(&VoidHandler)?;
|
||||
|
||||
Ok(VariableDeclarationAssignment { equals, expression })
|
||||
})
|
||||
|
@ -1053,37 +1040,6 @@ impl<'a> Parser<'a> {
|
|||
annotations: VecDeque::new(),
|
||||
}))
|
||||
}
|
||||
IndexingType::AnyString(selector) => {
|
||||
let equals = self.parse_punctuation('=', true, handler)?;
|
||||
let expression = self.parse_expression(handler)?;
|
||||
|
||||
let assignment = VariableDeclarationAssignment { equals, expression };
|
||||
|
||||
match variable_type.keyword {
|
||||
KeywordKind::Int => {
|
||||
Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
|
||||
int_keyword: variable_type,
|
||||
criteria: criteria_selection,
|
||||
identifier,
|
||||
open_bracket,
|
||||
close_bracket,
|
||||
target_assignment: Some((selector, assignment)),
|
||||
annotations: VecDeque::new(),
|
||||
}))
|
||||
}
|
||||
KeywordKind::Bool => {
|
||||
Ok(VariableDeclaration::Tag(TagVariableDeclaration {
|
||||
bool_keyword: variable_type,
|
||||
identifier,
|
||||
open_bracket,
|
||||
close_bracket,
|
||||
target_assignment: Some((selector, assignment)),
|
||||
annotations: VecDeque::new(),
|
||||
}))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
IndexingType::None => match variable_type.keyword {
|
||||
KeywordKind::Int => {
|
||||
Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
|
||||
|
@ -1092,7 +1048,7 @@ impl<'a> Parser<'a> {
|
|||
identifier,
|
||||
open_bracket,
|
||||
close_bracket,
|
||||
target_assignment: None,
|
||||
assignment: None,
|
||||
annotations: VecDeque::new(),
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -41,17 +41,6 @@ pub enum ComptimeValue {
|
|||
MacroString(MacroString),
|
||||
}
|
||||
|
||||
impl Display for ComptimeValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Boolean(boolean) => write!(f, "{boolean}"),
|
||||
Self::Integer(int) => write!(f, "{int}"),
|
||||
Self::String(string) => write!(f, "{string}"),
|
||||
Self::MacroString(macro_string) => write!(f, "{macro_string}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComptimeValue {
|
||||
/// Returns the value as a string not containing a macro.
|
||||
#[must_use]
|
||||
|
@ -63,6 +52,17 @@ impl ComptimeValue {
|
|||
Self::MacroString(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value as a [`MacroString`].
|
||||
#[must_use]
|
||||
pub fn to_macro_string(&self) -> MacroString {
|
||||
match self {
|
||||
Self::Boolean(boolean) => MacroString::String(boolean.to_string()),
|
||||
Self::Integer(int) => MacroString::String(int.to_string()),
|
||||
Self::String(string) => MacroString::String(string.clone()),
|
||||
Self::MacroString(macro_string) => macro_string.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of an expression.
|
||||
|
|
|
@ -441,7 +441,7 @@ impl Transpiler {
|
|||
Expression::Primary(Primary::Lua(lua)) => {
|
||||
lua.eval_comptime(scope, handler).and_then(|val| match val {
|
||||
Some(ComptimeValue::MacroString(s)) => Ok(Parameter::Static(s)),
|
||||
Some(val) => Ok(Parameter::Static(val.to_string().into())),
|
||||
Some(val) => Ok(Parameter::Static(val.to_macro_string())),
|
||||
None => {
|
||||
let err = TranspileError::MismatchedTypes(MismatchedTypes {
|
||||
expression: expression.span(),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![expect(unused)]
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
collections::{HashMap, VecDeque},
|
||||
fmt::Debug,
|
||||
ops::Deref,
|
||||
sync::{Arc, OnceLock, RwLock},
|
||||
|
@ -20,9 +20,10 @@ use crate::{
|
|||
syntax::syntax_tree::{
|
||||
expression::{Expression, Primary},
|
||||
statement::{
|
||||
AssignmentDestination, ScoreVariableDeclaration, SingleVariableDeclaration,
|
||||
VariableDeclaration,
|
||||
ArrayVariableDeclaration, AssignmentDestination, ScoreVariableDeclaration,
|
||||
SingleVariableDeclaration, TagVariableDeclaration, VariableDeclaration,
|
||||
},
|
||||
Annotation,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -247,8 +248,17 @@ impl Transpiler {
|
|||
scope,
|
||||
handler,
|
||||
),
|
||||
_ => todo!(
|
||||
"declarations other than single and scoreboard not supported yet: {declaration:?}"
|
||||
VariableDeclaration::Array(declaration) => self.transpile_array_variable_declaration(
|
||||
declaration,
|
||||
program_identifier,
|
||||
scope,
|
||||
handler,
|
||||
),
|
||||
VariableDeclaration::Tag(declaration) => self.transpile_tag_variable_declaration(
|
||||
declaration,
|
||||
program_identifier,
|
||||
scope,
|
||||
handler,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -316,23 +326,14 @@ impl Transpiler {
|
|||
scope: &Arc<Scope>,
|
||||
handler: &impl Handler<base::Error>,
|
||||
) -> TranspileResult<Vec<Command>> {
|
||||
let mut deobfuscate_annotations = declaration
|
||||
.annotations()
|
||||
.iter()
|
||||
.filter(|a| a.has_identifier("deobfuscate"));
|
||||
|
||||
let deobfuscate_annotation = deobfuscate_annotations.next();
|
||||
|
||||
if let Some(duplicate) = deobfuscate_annotations.next() {
|
||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||
annotation: duplicate.span(),
|
||||
message: "Multiple deobfuscate annotations are not allowed.".to_string(),
|
||||
});
|
||||
handler.receive(error.clone());
|
||||
return Err(error);
|
||||
}
|
||||
let name =
|
||||
self.get_data_location_identifier(declaration, program_identifier, scope, handler)?;
|
||||
let name = self.get_data_location_identifier(
|
||||
declaration.int_keyword().keyword,
|
||||
declaration.identifier(),
|
||||
declaration.annotations(),
|
||||
program_identifier,
|
||||
scope,
|
||||
handler,
|
||||
)?;
|
||||
|
||||
let criteria = declaration
|
||||
.criteria()
|
||||
|
@ -355,6 +356,84 @@ impl Transpiler {
|
|||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn transpile_array_variable_declaration(
|
||||
&mut self,
|
||||
declaration: &ArrayVariableDeclaration,
|
||||
program_identifier: &str,
|
||||
scope: &Arc<Scope>,
|
||||
handler: &impl Handler<base::Error>,
|
||||
) -> TranspileResult<Vec<Command>> {
|
||||
let variable_type = declaration.variable_type().keyword;
|
||||
|
||||
let (name, targets) =
|
||||
self.get_array_data_location_pair(declaration, program_identifier, scope, handler)?;
|
||||
|
||||
match variable_type {
|
||||
KeywordKind::Int => {
|
||||
if !self.datapack.scoreboards().contains_key(&name) {
|
||||
self.datapack
|
||||
.register_scoreboard(&name, None::<&str>, None::<&str>);
|
||||
}
|
||||
|
||||
scope.set_variable(
|
||||
declaration.identifier().span.str(),
|
||||
VariableData::ScoreboardArray {
|
||||
objective: name,
|
||||
targets,
|
||||
},
|
||||
);
|
||||
}
|
||||
KeywordKind::Bool => {
|
||||
scope.set_variable(
|
||||
declaration.identifier().span.str(),
|
||||
VariableData::BooleanStorageArray {
|
||||
storage_name: name,
|
||||
paths: targets,
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => unreachable!("no other variable types"),
|
||||
}
|
||||
|
||||
declaration.assignment().as_ref().map_or_else(
|
||||
|| Ok(Vec::new()),
|
||||
|assignment| {
|
||||
self.transpile_assignment(
|
||||
TranspileAssignmentTarget::Identifier(declaration.identifier()),
|
||||
assignment.expression(),
|
||||
scope,
|
||||
handler,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn transpile_tag_variable_declaration(
|
||||
&mut self,
|
||||
declaration: &TagVariableDeclaration,
|
||||
program_identifier: &str,
|
||||
scope: &Arc<Scope>,
|
||||
handler: &impl Handler<base::Error>,
|
||||
) -> TranspileResult<Vec<Command>> {
|
||||
let name = self.get_data_location_identifier(
|
||||
declaration.bool_keyword().keyword,
|
||||
declaration.identifier(),
|
||||
declaration.annotations(),
|
||||
program_identifier,
|
||||
scope,
|
||||
handler,
|
||||
)?;
|
||||
|
||||
scope.set_variable(
|
||||
declaration.identifier().span.str(),
|
||||
VariableData::Tag { tag_name: name },
|
||||
);
|
||||
|
||||
// TODO: implement assignment when map literal is implemented
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
pub(super) fn transpile_assignment(
|
||||
&mut self,
|
||||
destination: TranspileAssignmentTarget,
|
||||
|
@ -404,6 +483,7 @@ impl Transpiler {
|
|||
return Err(err);
|
||||
}
|
||||
None => {
|
||||
// TODO: allow when map literals are implemented
|
||||
let err = TranspileError::AssignmentError(AssignmentError {
|
||||
identifier: identifier.span(),
|
||||
message: "Cannot assign to a scoreboard without indexing".to_string(),
|
||||
|
@ -412,6 +492,138 @@ impl Transpiler {
|
|||
return Err(err);
|
||||
}
|
||||
},
|
||||
VariableData::ScoreboardArray { objective, targets } => {
|
||||
match indexing_value {
|
||||
Some(ComptimeValue::Integer(index)) => {
|
||||
if let Some(target) = usize::try_from(index)
|
||||
.ok()
|
||||
.and_then(|index| targets.get(index))
|
||||
{
|
||||
Ok(DataLocation::ScoreboardValue {
|
||||
objective: objective.to_string(),
|
||||
target: target.to_string(),
|
||||
})
|
||||
} else {
|
||||
let index_span = match destination {
|
||||
TranspileAssignmentTarget::Indexed(_, expr) => expr.span(),
|
||||
TranspileAssignmentTarget::Identifier(_) => unreachable!(
|
||||
"indexing value must be present (checked before)"
|
||||
),
|
||||
};
|
||||
let err = TranspileError::IllegalIndexing(IllegalIndexing {
|
||||
expression: index_span,
|
||||
reason: IllegalIndexingReason::IndexOutOfBounds {
|
||||
index: usize::try_from(index).unwrap_or(usize::MAX),
|
||||
length: targets.len(),
|
||||
},
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
Some(_) => {
|
||||
let err = TranspileError::IllegalIndexing(IllegalIndexing {
|
||||
expression: expression.span(),
|
||||
reason: IllegalIndexingReason::InvalidComptimeType {
|
||||
expected: ExpectedType::Integer,
|
||||
},
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
None => {
|
||||
// TODO: implement when array literals are implemented
|
||||
let err = TranspileError::AssignmentError(AssignmentError {
|
||||
identifier: identifier.span(),
|
||||
message: "Cannot assign to an array without indexing".to_string(),
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
VariableData::BooleanStorageArray {
|
||||
storage_name,
|
||||
paths,
|
||||
} => {
|
||||
match indexing_value {
|
||||
Some(ComptimeValue::Integer(index)) => {
|
||||
if let Some(path) = usize::try_from(index)
|
||||
.ok()
|
||||
.and_then(|index| paths.get(index))
|
||||
{
|
||||
Ok(DataLocation::Storage {
|
||||
storage_name: storage_name.to_string(),
|
||||
path: path.to_string(),
|
||||
r#type: StorageType::Boolean,
|
||||
})
|
||||
} else {
|
||||
let index_span = match destination {
|
||||
TranspileAssignmentTarget::Indexed(_, expr) => expr.span(),
|
||||
TranspileAssignmentTarget::Identifier(_) => unreachable!(
|
||||
"indexing value must be present (checked before)"
|
||||
),
|
||||
};
|
||||
let err = TranspileError::IllegalIndexing(IllegalIndexing {
|
||||
expression: index_span,
|
||||
reason: IllegalIndexingReason::IndexOutOfBounds {
|
||||
index: usize::try_from(index).unwrap_or(usize::MAX),
|
||||
length: paths.len(),
|
||||
},
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
Some(_) => {
|
||||
let err = TranspileError::IllegalIndexing(IllegalIndexing {
|
||||
expression: expression.span(),
|
||||
reason: IllegalIndexingReason::InvalidComptimeType {
|
||||
expected: ExpectedType::Integer,
|
||||
},
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
None => {
|
||||
// TODO: implement when array literals are implemented
|
||||
let err = TranspileError::AssignmentError(AssignmentError {
|
||||
identifier: identifier.span(),
|
||||
message: "Cannot assign to an array without indexing".to_string(),
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
VariableData::Tag { tag_name } => match indexing_value {
|
||||
Some(ComptimeValue::String(s)) => Ok(DataLocation::Tag {
|
||||
tag_name: tag_name.to_string(),
|
||||
entity: s,
|
||||
}),
|
||||
Some(ComptimeValue::MacroString(s)) => {
|
||||
todo!("indexing tag with macro string: {s}")
|
||||
}
|
||||
Some(_) => {
|
||||
let err = TranspileError::IllegalIndexing(IllegalIndexing {
|
||||
expression: expression.span(),
|
||||
reason: IllegalIndexingReason::InvalidComptimeType {
|
||||
expected: ExpectedType::String,
|
||||
},
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
None => {
|
||||
// TODO: allow when map literals are implemented
|
||||
let err = TranspileError::AssignmentError(AssignmentError {
|
||||
identifier: identifier.span(),
|
||||
message: "Cannot assign to a tag without indexing".to_string(),
|
||||
});
|
||||
handler.receive(err.clone());
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
VariableData::Function { .. } | VariableData::MacroParameter { .. } => {
|
||||
let err = TranspileError::AssignmentError(AssignmentError {
|
||||
identifier: identifier.span(),
|
||||
|
@ -427,7 +639,6 @@ impl Transpiler {
|
|||
handler.receive(err.clone());
|
||||
Err(err)
|
||||
}
|
||||
_ => todo!("implement other variable types"),
|
||||
}?;
|
||||
self.transpile_expression(expression, &data_location, scope, handler)
|
||||
} else {
|
||||
|
@ -442,13 +653,14 @@ impl Transpiler {
|
|||
|
||||
fn get_data_location_identifier(
|
||||
&mut self,
|
||||
declaration: &ScoreVariableDeclaration,
|
||||
variable_type: KeywordKind,
|
||||
identifier: &Identifier,
|
||||
annotations: &VecDeque<Annotation>,
|
||||
program_identifier: &str,
|
||||
scope: &Arc<Scope>,
|
||||
handler: &impl Handler<base::Error>,
|
||||
) -> TranspileResult<String> {
|
||||
let mut deobfuscate_annotations = declaration
|
||||
.annotations()
|
||||
let mut deobfuscate_annotations = annotations
|
||||
.iter()
|
||||
.filter(|a| a.has_identifier("deobfuscate"));
|
||||
|
||||
|
@ -472,6 +684,7 @@ impl Transpiler {
|
|||
.comptime_eval(scope, handler)
|
||||
.and_then(|val| val.to_string_no_macro())
|
||||
{
|
||||
// TODO: change invalid criteria if boolean
|
||||
if !crate::util::is_valid_scoreboard_objective_name(&name_eval) {
|
||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||
annotation: deobfuscate_annotation.span(),
|
||||
|
@ -490,9 +703,7 @@ impl Transpiler {
|
|||
Err(error)
|
||||
}
|
||||
}
|
||||
TranspileAnnotationValue::None => {
|
||||
Ok(declaration.identifier().span.str().to_string())
|
||||
}
|
||||
TranspileAnnotationValue::None => Ok(identifier.span.str().to_string()),
|
||||
TranspileAnnotationValue::Map(_) => {
|
||||
let error =
|
||||
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||
|
@ -507,7 +718,7 @@ impl Transpiler {
|
|||
} else {
|
||||
let hashed = md5::hash(program_identifier).to_hex_lowercase();
|
||||
let name = "shu_values_".to_string() + &hashed;
|
||||
let identifier_name = declaration.identifier().span.str();
|
||||
let identifier_name = identifier.span.str();
|
||||
let scope_ident = self.temp_counter;
|
||||
self.temp_counter = self.temp_counter.wrapping_add(1);
|
||||
let mut target = md5::hash(format!(
|
||||
|
@ -653,6 +864,97 @@ impl Transpiler {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_array_data_location_pair(
|
||||
&mut self,
|
||||
declaration: &ArrayVariableDeclaration,
|
||||
program_identifier: &str,
|
||||
scope: &Arc<Scope>,
|
||||
handler: &impl Handler<base::Error>,
|
||||
) -> TranspileResult<(String, Vec<String>)> {
|
||||
let mut deobfuscate_annotations = declaration
|
||||
.annotations()
|
||||
.iter()
|
||||
.filter(|a| a.has_identifier("deobfuscate"));
|
||||
|
||||
let variable_type = declaration.variable_type().keyword;
|
||||
|
||||
let deobfuscate_annotation = deobfuscate_annotations.next();
|
||||
|
||||
if let Some(duplicate) = deobfuscate_annotations.next() {
|
||||
let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||
annotation: duplicate.span(),
|
||||
message: "Multiple deobfuscate annotations are not allowed.".to_string(),
|
||||
});
|
||||
handler.receive(error.clone());
|
||||
return Err(error);
|
||||
}
|
||||
if let Some(deobfuscate_annotation) = deobfuscate_annotation {
|
||||
let deobfuscate_annotation_value =
|
||||
TranspileAnnotationValue::from(deobfuscate_annotation.assignment().value.clone());
|
||||
|
||||
match deobfuscate_annotation_value {
|
||||
TranspileAnnotationValue::None => {
|
||||
let ident_str = declaration.identifier().span.str();
|
||||
let name = if matches!(variable_type, KeywordKind::Int) {
|
||||
ident_str.to_string()
|
||||
} else {
|
||||
format!(
|
||||
"{namespace}:{ident_str}",
|
||||
namespace = self.main_namespace_name
|
||||
)
|
||||
};
|
||||
|
||||
let len = declaration.size().as_i64();
|
||||
let targets = (0..len).map(|i| i.to_string()).collect();
|
||||
Ok((name, targets))
|
||||
}
|
||||
TranspileAnnotationValue::Map(map) => {
|
||||
todo!("allow map deobfuscate annotation for array variables")
|
||||
}
|
||||
TranspileAnnotationValue::Expression(_) => {
|
||||
let error =
|
||||
TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
|
||||
annotation: deobfuscate_annotation.span(),
|
||||
message: "Deobfuscate annotation value must be a map or none."
|
||||
.to_string(),
|
||||
});
|
||||
handler.receive(error.clone());
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let hashed = md5::hash(program_identifier).to_hex_lowercase();
|
||||
let name = if matches!(variable_type, KeywordKind::Int) {
|
||||
"shu_values_"
|
||||
} else {
|
||||
"shulkerbox:values_"
|
||||
}
|
||||
.to_string()
|
||||
+ &hashed;
|
||||
let identifier_name = declaration.identifier().span.str();
|
||||
let scope_ident = self.temp_counter;
|
||||
self.temp_counter = self.temp_counter.wrapping_add(1);
|
||||
let len = declaration.size().as_i64();
|
||||
let targets = (0..len)
|
||||
.map(|i| {
|
||||
let mut target = md5::hash(format!(
|
||||
"{scope_ident}\0{identifier_name}\0{i}\0{shadowed}",
|
||||
shadowed = scope.get_variable_shadow_count(identifier_name)
|
||||
))
|
||||
.to_hex_lowercase();
|
||||
|
||||
if matches!(variable_type, KeywordKind::Int) {
|
||||
target.split_off(16);
|
||||
}
|
||||
|
||||
target
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok((name, targets))
|
||||
}
|
||||
}
|
||||
|
||||
/// Move data from location `from` to location `to`.
|
||||
///
|
||||
/// # Errors
|
||||
|
|
Loading…
Reference in New Issue