Compare commits
	
		
			No commits in common. "bd8270bd5dc814222bb9b5f74820dd9d13714533" and "3271ca514c9243877df5a62cbe8650860da27d7e" have entirely different histories.
		
	
	
		
			bd8270bd5d
			...
			3271ca514c
		
	
		| 
						 | 
					@ -19,7 +19,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 | 
				
			||||||
    - Boolean map (tag)
 | 
					    - Boolean map (tag)
 | 
				
			||||||
    - Member access (e.g. `.objective` to get objective name where int is stored)
 | 
					    - Member access (e.g. `.objective` to get objective name where int is stored)
 | 
				
			||||||
- Return statement
 | 
					- Return statement
 | 
				
			||||||
- internal `print` function
 | 
					 | 
				
			||||||
- Example: barebones compiler
 | 
					- Example: barebones compiler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Changed
 | 
					### Changed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ FunctionParameterList:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ebnf
 | 
					```ebnf
 | 
				
			||||||
ArrayVariableDeclaration:
 | 
					ArrayVariableDeclaration:
 | 
				
			||||||
    ('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment?
 | 
					    ('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## ComptimeValueDeclaration
 | 
					## ComptimeValueDeclaration
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,11 +7,11 @@ pub enum Error {
 | 
				
			||||||
    #[error(transparent)]
 | 
					    #[error(transparent)]
 | 
				
			||||||
    LexicalError(#[from] crate::lexical::Error),
 | 
					    LexicalError(#[from] crate::lexical::Error),
 | 
				
			||||||
    #[error(transparent)]
 | 
					    #[error(transparent)]
 | 
				
			||||||
    ParseError(#[from] Box<crate::syntax::error::Error>),
 | 
					    ParseError(#[from] crate::syntax::error::Error),
 | 
				
			||||||
    #[error(transparent)]
 | 
					    #[error(transparent)]
 | 
				
			||||||
    SemanticError(#[from] crate::semantic::error::Error),
 | 
					    SemanticError(#[from] crate::semantic::error::Error),
 | 
				
			||||||
    #[error(transparent)]
 | 
					    #[error(transparent)]
 | 
				
			||||||
    TranspileError(#[from] Box<crate::transpile::TranspileError>),
 | 
					    TranspileError(#[from] crate::transpile::TranspileError),
 | 
				
			||||||
    #[error("An error occurred: {0}")]
 | 
					    #[error("An error occurred: {0}")]
 | 
				
			||||||
    Other(String),
 | 
					    Other(String),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ pub trait FileProvider {
 | 
				
			||||||
    /// # Errors
 | 
					    /// # Errors
 | 
				
			||||||
    /// - If an error occurs while reading the file.
 | 
					    /// - If an error occurs while reading the file.
 | 
				
			||||||
    /// - If the file does not exist.
 | 
					    /// - If the file does not exist.
 | 
				
			||||||
    fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, [u8]>, Error>;
 | 
					    fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<[u8]>, Error>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Reads the contents of the file at the given path.
 | 
					    /// Reads the contents of the file at the given path.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ pub trait FileProvider {
 | 
				
			||||||
    /// - If an error occurs while reading the file.
 | 
					    /// - If an error occurs while reading the file.
 | 
				
			||||||
    /// - If the file does not exist.
 | 
					    /// - If the file does not exist.
 | 
				
			||||||
    /// - If the file is not valid UTF-8.
 | 
					    /// - If the file is not valid UTF-8.
 | 
				
			||||||
    fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, str>, Error> {
 | 
					    fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<str>, Error> {
 | 
				
			||||||
        let bytes = self.read_bytes(path)?;
 | 
					        let bytes = self.read_bytes(path)?;
 | 
				
			||||||
        let string = std::str::from_utf8(&bytes)
 | 
					        let string = std::str::from_utf8(&bytes)
 | 
				
			||||||
            .map_err(|err| {
 | 
					            .map_err(|err| {
 | 
				
			||||||
| 
						 | 
					@ -57,14 +57,14 @@ where
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FileProvider for FsProvider {
 | 
					impl FileProvider for FsProvider {
 | 
				
			||||||
    fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, [u8]>, Error> {
 | 
					    fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<[u8]>, Error> {
 | 
				
			||||||
        let full_path = self.root.join(path);
 | 
					        let full_path = self.root.join(path);
 | 
				
			||||||
        std::fs::read(full_path)
 | 
					        std::fs::read(full_path)
 | 
				
			||||||
            .map(Cow::Owned)
 | 
					            .map(Cow::Owned)
 | 
				
			||||||
            .map_err(Error::from)
 | 
					            .map_err(Error::from)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, str>, Error> {
 | 
					    fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<str>, Error> {
 | 
				
			||||||
        let full_path = self.root.join(path);
 | 
					        let full_path = self.root.join(path);
 | 
				
			||||||
        std::fs::read_to_string(full_path)
 | 
					        std::fs::read_to_string(full_path)
 | 
				
			||||||
            .map(Cow::Owned)
 | 
					            .map(Cow::Owned)
 | 
				
			||||||
| 
						 | 
					@ -178,7 +178,7 @@ mod vfs {
 | 
				
			||||||
    use shulkerbox::virtual_fs::{VFile, VFolder};
 | 
					    use shulkerbox::virtual_fs::{VFile, VFolder};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    impl FileProvider for VFolder {
 | 
					    impl FileProvider for VFolder {
 | 
				
			||||||
        fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, [u8]>, Error> {
 | 
					        fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Cow<[u8]>, Error> {
 | 
				
			||||||
            normalize_path_str(path).map_or_else(
 | 
					            normalize_path_str(path).map_or_else(
 | 
				
			||||||
                || Err(Error::from(std::io::ErrorKind::InvalidData)),
 | 
					                || Err(Error::from(std::io::ErrorKind::InvalidData)),
 | 
				
			||||||
                |path| {
 | 
					                |path| {
 | 
				
			||||||
| 
						 | 
					@ -189,7 +189,7 @@ mod vfs {
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<'_, str>, Error> {
 | 
					        fn read_str<P: AsRef<Path>>(&self, path: P) -> Result<Cow<str>, Error> {
 | 
				
			||||||
            normalize_path_str(path).map_or_else(
 | 
					            normalize_path_str(path).map_or_else(
 | 
				
			||||||
                || Err(Error::from(std::io::ErrorKind::InvalidData)),
 | 
					                || Err(Error::from(std::io::ErrorKind::InvalidData)),
 | 
				
			||||||
                |path| {
 | 
					                |path| {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,7 @@ impl SourceFile {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get the [`SourceIterator`] for the source file.
 | 
					    /// Get the [`SourceIterator`] for the source file.
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn iter(self: &Arc<Self>) -> SourceIterator<'_> {
 | 
					    pub fn iter<'a>(self: &'a Arc<Self>) -> SourceIterator<'a> {
 | 
				
			||||||
        SourceIterator {
 | 
					        SourceIterator {
 | 
				
			||||||
            source_file: self,
 | 
					            source_file: self,
 | 
				
			||||||
            iterator: self.content().char_indices().peekable(),
 | 
					            iterator: self.content().char_indices().peekable(),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,7 +161,7 @@ pub enum Token {
 | 
				
			||||||
    DocComment(DocComment),
 | 
					    DocComment(DocComment),
 | 
				
			||||||
    CommandLiteral(CommandLiteral),
 | 
					    CommandLiteral(CommandLiteral),
 | 
				
			||||||
    StringLiteral(StringLiteral),
 | 
					    StringLiteral(StringLiteral),
 | 
				
			||||||
    MacroStringLiteral(Box<MacroStringLiteral>),
 | 
					    MacroStringLiteral(MacroStringLiteral),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SourceElement for Token {
 | 
					impl SourceElement for Token {
 | 
				
			||||||
| 
						 | 
					@ -325,7 +325,7 @@ pub struct StringLiteral {
 | 
				
			||||||
impl StringLiteral {
 | 
					impl StringLiteral {
 | 
				
			||||||
    /// Returns the string content without escapement characters, leading and trailing double quotes.
 | 
					    /// Returns the string content without escapement characters, leading and trailing double quotes.
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn str_content(&self) -> Cow<'_, str> {
 | 
					    pub fn str_content(&self) -> Cow<str> {
 | 
				
			||||||
        let string = self.span.str();
 | 
					        let string = self.span.str();
 | 
				
			||||||
        let string = &string[1..string.len() - 1];
 | 
					        let string = &string[1..string.len() - 1];
 | 
				
			||||||
        if string.contains('\\') {
 | 
					        if string.contains('\\') {
 | 
				
			||||||
| 
						 | 
					@ -740,7 +740,7 @@ impl Token {
 | 
				
			||||||
                handler.receive(error::Error::from(UnterminatedDelimitedComment {
 | 
					                handler.receive(error::Error::from(UnterminatedDelimitedComment {
 | 
				
			||||||
                    span: Span::new(iter.source_file().clone(), start, start + 2).unwrap(),
 | 
					                    span: Span::new(iter.source_file().clone(), start, start + 2).unwrap(),
 | 
				
			||||||
                }));
 | 
					                }));
 | 
				
			||||||
                Err(TokenizeError::FatalLexicalError)
 | 
					                return Err(TokenizeError::FatalLexicalError);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // When there is no second slash and at the start of a line
 | 
					        // When there is no second slash and at the start of a line
 | 
				
			||||||
| 
						 | 
					@ -883,14 +883,14 @@ impl Token {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            .into())
 | 
					            .into())
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Ok(Box::new(MacroStringLiteral {
 | 
					            Ok(MacroStringLiteral {
 | 
				
			||||||
                starting_backtick,
 | 
					                starting_backtick,
 | 
				
			||||||
                parts,
 | 
					                parts,
 | 
				
			||||||
                ending_backtick: Punctuation {
 | 
					                ending_backtick: Punctuation {
 | 
				
			||||||
                    span: Self::create_span(start, iter),
 | 
					                    span: Self::create_span(start, iter),
 | 
				
			||||||
                    punctuation: '`',
 | 
					                    punctuation: '`',
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            })
 | 
					            }
 | 
				
			||||||
            .into())
 | 
					            .into())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,7 @@ pub fn parse(
 | 
				
			||||||
    tracing::info!("Parsing the source code at path: {}", path.display());
 | 
					    tracing::info!("Parsing the source code at path: {}", path.display());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut parser = Parser::new(&tokens);
 | 
					    let mut parser = Parser::new(&tokens);
 | 
				
			||||||
    let program = parser.parse_program(handler).map_err(Box::new)?;
 | 
					    let program = parser.parse_program(handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if handler.has_received() {
 | 
					    if handler.has_received() {
 | 
				
			||||||
        return Err(Error::other(
 | 
					        return Err(Error::other(
 | 
				
			||||||
| 
						 | 
					@ -165,9 +165,8 @@ where
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tracing::info!("Transpiling the source code.");
 | 
					    tracing::info!("Transpiling the source code.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let datapack = Transpiler::new(main_namespace_name, pack_format)
 | 
					    let datapack =
 | 
				
			||||||
        .transpile(&programs, handler)
 | 
					        Transpiler::new(main_namespace_name, pack_format).transpile(&programs, handler)?;
 | 
				
			||||||
        .map_err(Box::new)?;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if handler.has_received() {
 | 
					    if handler.has_received() {
 | 
				
			||||||
        return Err(Error::other(
 | 
					        return Err(Error::other(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ pub enum Error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// An error that occurs when a function declaration is missing.
 | 
					/// An error that occurs when a function declaration is missing.
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 | 
				
			||||||
pub struct UnexpectedExpression(pub Box<Expression>);
 | 
					pub struct UnexpectedExpression(pub Expression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Display for UnexpectedExpression {
 | 
					impl Display for UnexpectedExpression {
 | 
				
			||||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,7 @@ fn get_global_scope(declarations: &[Declaration]) -> SemanticScope<'static> {
 | 
				
			||||||
impl Namespace {
 | 
					impl Namespace {
 | 
				
			||||||
    /// Analyzes the semantics of the namespace.
 | 
					    /// Analyzes the semantics of the namespace.
 | 
				
			||||||
    fn analyze_semantics(&self, handler: &impl Handler<base::Error>) -> Result<(), error::Error> {
 | 
					    fn analyze_semantics(&self, handler: &impl Handler<base::Error>) -> Result<(), error::Error> {
 | 
				
			||||||
        let name = self.name();
 | 
					        let name = self.namespace_name();
 | 
				
			||||||
        Self::validate_str(name.str_content().as_ref()).map_err(|invalid_chars| {
 | 
					        Self::validate_str(name.str_content().as_ref()).map_err(|invalid_chars| {
 | 
				
			||||||
            let err = error::Error::from(InvalidNamespaceName {
 | 
					            let err = error::Error::from(InvalidNamespaceName {
 | 
				
			||||||
                name: name.clone(),
 | 
					                name: name.clone(),
 | 
				
			||||||
| 
						 | 
					@ -393,22 +393,12 @@ impl Assignment {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(variable_type) = variable_type {
 | 
					        if let Some(variable_type) = variable_type {
 | 
				
			||||||
            let expected = match variable_type {
 | 
					            let expected = match variable_type {
 | 
				
			||||||
                VariableType::BooleanStorage => ValueType::Boolean,
 | 
					                VariableType::BooleanStorage | VariableType::Tag => ValueType::Boolean,
 | 
				
			||||||
                VariableType::ScoreboardValue => ValueType::Integer,
 | 
					                VariableType::ScoreboardValue => ValueType::Integer,
 | 
				
			||||||
                VariableType::ComptimeValue => {
 | 
					                VariableType::ComptimeValue => {
 | 
				
			||||||
                    // TODO: check if the expression is a constant expression
 | 
					                    // TODO: check if the expression is a constant expression
 | 
				
			||||||
                    return Ok(());
 | 
					                    return Ok(());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                VariableType::BooleanStorageArray | VariableType::Tag
 | 
					 | 
				
			||||||
                    if matches!(self.destination(), AssignmentDestination::Indexed(..)) =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    ValueType::Boolean
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                VariableType::Scoreboard | VariableType::ScoreboardArray
 | 
					 | 
				
			||||||
                    if matches!(self.destination(), AssignmentDestination::Indexed(..)) =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    ValueType::Integer
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
                    let err = error::Error::AssignmentError(AssignmentError {
 | 
					                    let err = error::Error::AssignmentError(AssignmentError {
 | 
				
			||||||
                        identifier: self.destination().span(),
 | 
					                        identifier: self.destination().span(),
 | 
				
			||||||
| 
						 | 
					@ -571,7 +561,7 @@ impl Primary {
 | 
				
			||||||
                        VariableType::Function | VariableType::InternalFunction => Ok(()),
 | 
					                        VariableType::Function | VariableType::InternalFunction => Ok(()),
 | 
				
			||||||
                        _ => {
 | 
					                        _ => {
 | 
				
			||||||
                            let err = error::Error::UnexpectedExpression(UnexpectedExpression(
 | 
					                            let err = error::Error::UnexpectedExpression(UnexpectedExpression(
 | 
				
			||||||
                                Box::new(Expression::Primary(self.clone())),
 | 
					                                Expression::Primary(self.clone()),
 | 
				
			||||||
                            ));
 | 
					                            ));
 | 
				
			||||||
                            handler.receive(err.clone());
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
| 
						 | 
					@ -716,14 +706,13 @@ impl Primary {
 | 
				
			||||||
                _ => false,
 | 
					                _ => false,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            Self::MemberAccess(_) => {
 | 
					            Self::MemberAccess(_) => {
 | 
				
			||||||
                // TODO: correct return value after check
 | 
					                // TODO:
 | 
				
			||||||
                true
 | 
					                true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Self::Identifier(ident) => match scope.get_variable(ident.span.str()) {
 | 
					            Self::Identifier(ident) => match scope.get_variable(ident.span.str()) {
 | 
				
			||||||
                Some(VariableType::BooleanStorage) => expected == ValueType::Boolean,
 | 
					                Some(VariableType::BooleanStorage) => expected == ValueType::Boolean,
 | 
				
			||||||
                Some(VariableType::ScoreboardValue) => expected == ValueType::Integer,
 | 
					                Some(VariableType::ScoreboardValue) => expected == ValueType::Integer,
 | 
				
			||||||
                Some(VariableType::Tag) => expected == ValueType::String,
 | 
					                Some(VariableType::Tag) => expected == ValueType::String,
 | 
				
			||||||
                Some(VariableType::ComptimeValue) => true,
 | 
					 | 
				
			||||||
                _ => false,
 | 
					                _ => false,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            Self::Prefix(prefixed) => match prefixed.operator() {
 | 
					            Self::Prefix(prefixed) => match prefixed.operator() {
 | 
				
			||||||
| 
						 | 
					@ -941,10 +930,9 @@ impl MacroStringLiteral {
 | 
				
			||||||
                MacroStringLiteralPart::MacroUsage { identifier, .. } => {
 | 
					                MacroStringLiteralPart::MacroUsage { identifier, .. } => {
 | 
				
			||||||
                    if let Some(variable_type) = scope.get_variable(identifier.span.str()) {
 | 
					                    if let Some(variable_type) = scope.get_variable(identifier.span.str()) {
 | 
				
			||||||
                        if variable_type != VariableType::MacroParameter {
 | 
					                        if variable_type != VariableType::MacroParameter {
 | 
				
			||||||
                            let err =
 | 
					                            let err = error::Error::UnexpectedExpression(UnexpectedExpression(
 | 
				
			||||||
                                error::Error::UnexpectedExpression(UnexpectedExpression(Box::new(
 | 
					 | 
				
			||||||
                                Expression::Primary(Primary::Identifier(identifier.clone())),
 | 
					                                Expression::Primary(Primary::Identifier(identifier.clone())),
 | 
				
			||||||
                                )));
 | 
					                            ));
 | 
				
			||||||
                            handler.receive(err.clone());
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            errs.push(err);
 | 
					                            errs.push(err);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,7 @@ impl<'a> Parser<'a> {
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }),
 | 
					                        }),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return Err(err);
 | 
					                    return Err(err);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ impl<'a> Parser<'a> {
 | 
				
			||||||
                expected: SyntaxKind::Punctuation(expected),
 | 
					                expected: SyntaxKind::Punctuation(expected),
 | 
				
			||||||
                found: self.get_reading(None).into_token(),
 | 
					                found: self.get_reading(None).into_token(),
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            handler.receive(Box::new(err.clone()));
 | 
					            handler.receive(err.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Err(err);
 | 
					            return Err(err);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ impl<'a> Parser<'a> {
 | 
				
			||||||
                expected: SyntaxKind::Punctuation(expected),
 | 
					                expected: SyntaxKind::Punctuation(expected),
 | 
				
			||||||
                found: self.peek().into_token(),
 | 
					                found: self.peek().into_token(),
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            handler.receive(Box::new(err.clone()));
 | 
					            handler.receive(err.clone());
 | 
				
			||||||
            return Err(err);
 | 
					            return Err(err);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -393,7 +393,7 @@ impl Frame<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::Identifier,
 | 
					                    expected: SyntaxKind::Identifier,
 | 
				
			||||||
                    found: found.into_token(),
 | 
					                    found: found.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -432,7 +432,7 @@ impl Frame<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::StringLiteral,
 | 
					                    expected: SyntaxKind::StringLiteral,
 | 
				
			||||||
                    found: found.into_token(),
 | 
					                    found: found.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -447,13 +447,13 @@ impl Frame<'_> {
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> ParseResult<MacroStringLiteral> {
 | 
					    ) -> ParseResult<MacroStringLiteral> {
 | 
				
			||||||
        match self.next_significant_token() {
 | 
					        match self.next_significant_token() {
 | 
				
			||||||
            Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok(*literal),
 | 
					            Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok(literal),
 | 
				
			||||||
            found => {
 | 
					            found => {
 | 
				
			||||||
                let err = Error::UnexpectedSyntax(UnexpectedSyntax {
 | 
					                let err = Error::UnexpectedSyntax(UnexpectedSyntax {
 | 
				
			||||||
                    expected: SyntaxKind::MacroStringLiteral,
 | 
					                    expected: SyntaxKind::MacroStringLiteral,
 | 
				
			||||||
                    found: found.into_token(),
 | 
					                    found: found.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -469,13 +469,13 @@ impl Frame<'_> {
 | 
				
			||||||
    ) -> ParseResult<AnyStringLiteral> {
 | 
					    ) -> ParseResult<AnyStringLiteral> {
 | 
				
			||||||
        match self.next_significant_token() {
 | 
					        match self.next_significant_token() {
 | 
				
			||||||
            Reading::Atomic(Token::StringLiteral(literal)) => Ok(literal.into()),
 | 
					            Reading::Atomic(Token::StringLiteral(literal)) => Ok(literal.into()),
 | 
				
			||||||
            Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok((*literal).into()),
 | 
					            Reading::Atomic(Token::MacroStringLiteral(literal)) => Ok(literal.into()),
 | 
				
			||||||
            found => {
 | 
					            found => {
 | 
				
			||||||
                let err = Error::UnexpectedSyntax(UnexpectedSyntax {
 | 
					                let err = Error::UnexpectedSyntax(UnexpectedSyntax {
 | 
				
			||||||
                    expected: SyntaxKind::AnyStringLiteral,
 | 
					                    expected: SyntaxKind::AnyStringLiteral,
 | 
				
			||||||
                    found: found.into_token(),
 | 
					                    found: found.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -499,7 +499,7 @@ impl Frame<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::Keyword(expected),
 | 
					                    expected: SyntaxKind::Keyword(expected),
 | 
				
			||||||
                    found: found.into_token(),
 | 
					                    found: found.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -530,7 +530,7 @@ impl Frame<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::Punctuation(expected),
 | 
					                    expected: SyntaxKind::Punctuation(expected),
 | 
				
			||||||
                    found: found.into_token(),
 | 
					                    found: found.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
//! Syntax tree nodes for declarations.
 | 
					//! Syntax tree nodes for declarations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#![expect(missing_docs)]
 | 
					#![allow(missing_docs)]
 | 
				
			||||||
#![expect(clippy::struct_field_names)]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::collections::VecDeque;
 | 
					use std::collections::VecDeque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -392,7 +391,7 @@ impl Parser<'_> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                declaration
 | 
					                declaration
 | 
				
			||||||
                    .with_annotation(annotation)
 | 
					                    .with_annotation(annotation)
 | 
				
			||||||
                    .inspect_err(|err| handler.receive(Box::new(err.clone())))
 | 
					                    .inspect_err(|err| handler.receive(err.clone()))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Reading::Atomic(Token::Keyword(from_keyword))
 | 
					            Reading::Atomic(Token::Keyword(from_keyword))
 | 
				
			||||||
| 
						 | 
					@ -442,7 +441,7 @@ impl Parser<'_> {
 | 
				
			||||||
                        expected: SyntaxKind::Punctuation('*'),
 | 
					                        expected: SyntaxKind::Punctuation('*'),
 | 
				
			||||||
                        found: self.stop_at_significant().into_token(),
 | 
					                        found: self.stop_at_significant().into_token(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -512,7 +511,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::Declaration,
 | 
					                    expected: SyntaxKind::Declaration,
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -563,7 +562,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::Keyword(KeywordKind::Function),
 | 
					                    expected: SyntaxKind::Keyword(KeywordKind::Function),
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -616,7 +615,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    ]),
 | 
					                    ]),
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -666,7 +666,7 @@ impl Parser<'_> {
 | 
				
			||||||
                // eat the macro string literal
 | 
					                // eat the macro string literal
 | 
				
			||||||
                self.forward();
 | 
					                self.forward();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Ok(Primary::MacroStringLiteral(*macro_string_literal))
 | 
					                Ok(Primary::MacroStringLiteral(macro_string_literal))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // lua code expression
 | 
					            // lua code expression
 | 
				
			||||||
| 
						 | 
					@ -687,7 +687,7 @@ impl Parser<'_> {
 | 
				
			||||||
                                expected: syntax::error::SyntaxKind::Identifier,
 | 
					                                expected: syntax::error::SyntaxKind::Identifier,
 | 
				
			||||||
                                found: unexpected.into_token(),
 | 
					                                found: unexpected.into_token(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
| 
						 | 
					@ -741,7 +741,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: syntax::error::SyntaxKind::Expression,
 | 
					                    expected: syntax::error::SyntaxKind::Expression,
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -829,7 +829,7 @@ impl Parser<'_> {
 | 
				
			||||||
                        expected: syntax::error::SyntaxKind::Operator,
 | 
					                        expected: syntax::error::SyntaxKind::Operator,
 | 
				
			||||||
                        found: Some(Token::Punctuation(punc)),
 | 
					                        found: Some(Token::Punctuation(punc)),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -838,7 +838,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: syntax::error::SyntaxKind::Operator,
 | 
					                    expected: syntax::error::SyntaxKind::Operator,
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -388,7 +388,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::Punctuation('#'),
 | 
					                    expected: SyntaxKind::Punctuation('#'),
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,10 +52,10 @@ pub struct ProgramFile {
 | 
				
			||||||
pub struct Namespace {
 | 
					pub struct Namespace {
 | 
				
			||||||
    /// The `namespace` keyword.
 | 
					    /// The `namespace` keyword.
 | 
				
			||||||
    #[get = "pub"]
 | 
					    #[get = "pub"]
 | 
				
			||||||
    keyword: Keyword,
 | 
					    namespace_keyword: Keyword,
 | 
				
			||||||
    /// The name of the namespace.
 | 
					    /// The name of the namespace.
 | 
				
			||||||
    #[get = "pub"]
 | 
					    #[get = "pub"]
 | 
				
			||||||
    name: StringLiteral,
 | 
					    namespace_name: StringLiteral,
 | 
				
			||||||
    /// The semicolon.
 | 
					    /// The semicolon.
 | 
				
			||||||
    #[get = "pub"]
 | 
					    #[get = "pub"]
 | 
				
			||||||
    semicolon: Punctuation,
 | 
					    semicolon: Punctuation,
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ pub struct Namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SourceElement for Namespace {
 | 
					impl SourceElement for Namespace {
 | 
				
			||||||
    fn span(&self) -> Span {
 | 
					    fn span(&self) -> Span {
 | 
				
			||||||
        self.keyword
 | 
					        self.namespace_keyword
 | 
				
			||||||
            .span()
 | 
					            .span()
 | 
				
			||||||
            .join(&self.semicolon.span())
 | 
					            .join(&self.semicolon.span())
 | 
				
			||||||
            .expect("Invalid span")
 | 
					            .expect("Invalid span")
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ impl Namespace {
 | 
				
			||||||
    /// Dissolves the namespace into its components.
 | 
					    /// Dissolves the namespace into its components.
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn dissolve(self) -> (Keyword, StringLiteral, Punctuation) {
 | 
					    pub fn dissolve(self) -> (Keyword, StringLiteral, Punctuation) {
 | 
				
			||||||
        (self.keyword, self.name, self.semicolon)
 | 
					        (self.namespace_keyword, self.namespace_name, self.semicolon)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Validates a namespace string.
 | 
					    /// Validates a namespace string.
 | 
				
			||||||
| 
						 | 
					@ -112,19 +112,19 @@ impl Parser<'_> {
 | 
				
			||||||
        tracing::debug!("Parsing program");
 | 
					        tracing::debug!("Parsing program");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let namespace = match self.stop_at_significant() {
 | 
					        let namespace = match self.stop_at_significant() {
 | 
				
			||||||
            Reading::Atomic(Token::Keyword(keyword))
 | 
					            Reading::Atomic(Token::Keyword(namespace_keyword))
 | 
				
			||||||
                if keyword.keyword == KeywordKind::Namespace =>
 | 
					                if namespace_keyword.keyword == KeywordKind::Namespace =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // eat the keyword
 | 
					                // eat the keyword
 | 
				
			||||||
                self.forward();
 | 
					                self.forward();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let name = self.parse_string_literal(handler)?;
 | 
					                let namespace_name = self.parse_string_literal(handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let semicolon = self.parse_punctuation(';', true, handler)?;
 | 
					                let semicolon = self.parse_punctuation(';', true, handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Ok(Namespace {
 | 
					                Ok(Namespace {
 | 
				
			||||||
                    keyword,
 | 
					                    namespace_keyword,
 | 
				
			||||||
                    name,
 | 
					                    namespace_name,
 | 
				
			||||||
                    semicolon,
 | 
					                    semicolon,
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -133,14 +133,14 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::Keyword(KeywordKind::Namespace),
 | 
					                    expected: SyntaxKind::Keyword(KeywordKind::Namespace),
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }?;
 | 
					        }?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tracing::debug!(
 | 
					        tracing::debug!(
 | 
				
			||||||
            "Found namespace '{}', parsing declarations",
 | 
					            "Found namespace '{}', parsing declarations",
 | 
				
			||||||
            namespace.name.str_content()
 | 
					            namespace.namespace_name.str_content()
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut declarations = Vec::new();
 | 
					        let mut declarations = Vec::new();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -493,7 +493,7 @@ impl SingleVariableDeclaration {
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// ```ebnf
 | 
					/// ```ebnf
 | 
				
			||||||
/// ArrayVariableDeclaration:
 | 
					/// ArrayVariableDeclaration:
 | 
				
			||||||
///     ('int' | 'bool') '[' integer ']' identifier VariableDeclarationAssignment?
 | 
					///     ('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
 | 
				
			||||||
/// ```
 | 
					/// ```
 | 
				
			||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
 | 
					#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
 | 
				
			||||||
| 
						 | 
					@ -501,6 +501,9 @@ pub struct ArrayVariableDeclaration {
 | 
				
			||||||
    /// The type of the variable.
 | 
					    /// The type of the variable.
 | 
				
			||||||
    #[get = "pub"]
 | 
					    #[get = "pub"]
 | 
				
			||||||
    variable_type: Keyword,
 | 
					    variable_type: Keyword,
 | 
				
			||||||
 | 
					    /// The identifier of the variable.
 | 
				
			||||||
 | 
					    #[get = "pub"]
 | 
				
			||||||
 | 
					    identifier: Identifier,
 | 
				
			||||||
    /// The opening bracket of the array.
 | 
					    /// The opening bracket of the array.
 | 
				
			||||||
    #[get = "pub"]
 | 
					    #[get = "pub"]
 | 
				
			||||||
    open_bracket: Punctuation,
 | 
					    open_bracket: Punctuation,
 | 
				
			||||||
| 
						 | 
					@ -510,9 +513,6 @@ pub struct ArrayVariableDeclaration {
 | 
				
			||||||
    /// The closing bracket of the array.
 | 
					    /// The closing bracket of the array.
 | 
				
			||||||
    #[get = "pub"]
 | 
					    #[get = "pub"]
 | 
				
			||||||
    close_bracket: Punctuation,
 | 
					    close_bracket: Punctuation,
 | 
				
			||||||
    /// The identifier of the variable.
 | 
					 | 
				
			||||||
    #[get = "pub"]
 | 
					 | 
				
			||||||
    identifier: Identifier,
 | 
					 | 
				
			||||||
    /// The optional assignment of the variable.
 | 
					    /// The optional assignment of the variable.
 | 
				
			||||||
    #[get = "pub"]
 | 
					    #[get = "pub"]
 | 
				
			||||||
    assignment: Option<VariableDeclarationAssignment>,
 | 
					    assignment: Option<VariableDeclarationAssignment>,
 | 
				
			||||||
| 
						 | 
					@ -798,7 +798,7 @@ pub enum AssignmentDestination {
 | 
				
			||||||
    /// Assignment to an identifier.
 | 
					    /// Assignment to an identifier.
 | 
				
			||||||
    Identifier(Identifier),
 | 
					    Identifier(Identifier),
 | 
				
			||||||
    /// Assignment to an indexed identifier.
 | 
					    /// Assignment to an indexed identifier.
 | 
				
			||||||
    Indexed(Identifier, Punctuation, Box<Expression>, Punctuation),
 | 
					    Indexed(Identifier, Punctuation, Expression, Punctuation),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SourceElement for AssignmentDestination {
 | 
					impl SourceElement for AssignmentDestination {
 | 
				
			||||||
| 
						 | 
					@ -872,7 +872,7 @@ impl Parser<'_> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                statement
 | 
					                statement
 | 
				
			||||||
                    .with_annotation(annotation)
 | 
					                    .with_annotation(annotation)
 | 
				
			||||||
                    .inspect_err(|err| handler.receive(Box::new(err.clone())))
 | 
					                    .inspect_err(|err| handler.receive(err.clone()))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // variable declaration
 | 
					            // variable declaration
 | 
				
			||||||
            Reading::Atomic(Token::CommandLiteral(command)) => {
 | 
					            Reading::Atomic(Token::CommandLiteral(command)) => {
 | 
				
			||||||
| 
						 | 
					@ -971,12 +971,7 @@ impl Parser<'_> {
 | 
				
			||||||
                                let close = tree.close;
 | 
					                                let close = tree.close;
 | 
				
			||||||
                                let expression = tree.tree?;
 | 
					                                let expression = tree.tree?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                AssignmentDestination::Indexed(
 | 
					                                AssignmentDestination::Indexed(identifier, open, expression, close)
 | 
				
			||||||
                                    identifier,
 | 
					 | 
				
			||||||
                                    open,
 | 
					 | 
				
			||||||
                                    Box::new(expression),
 | 
					 | 
				
			||||||
                                    close,
 | 
					 | 
				
			||||||
                                )
 | 
					 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            _ => AssignmentDestination::Identifier(identifier),
 | 
					                            _ => AssignmentDestination::Identifier(identifier),
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -1041,7 +1036,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    ]),
 | 
					                    ]),
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                return Err(err);
 | 
					                return Err(err);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
| 
						 | 
					@ -1058,7 +1053,11 @@ impl Parser<'_> {
 | 
				
			||||||
            None
 | 
					            None
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let index = match self.stop_at_significant() {
 | 
					        // read identifier
 | 
				
			||||||
 | 
					        self.stop_at_significant();
 | 
				
			||||||
 | 
					        let identifier = self.parse_identifier(handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match self.stop_at_significant() {
 | 
				
			||||||
            Reading::IntoDelimited(punc)
 | 
					            Reading::IntoDelimited(punc)
 | 
				
			||||||
                if punc.punctuation == '['
 | 
					                if punc.punctuation == '['
 | 
				
			||||||
                    && matches!(variable_type.keyword, KeywordKind::Int | KeywordKind::Bool) =>
 | 
					                    && matches!(variable_type.keyword, KeywordKind::Int | KeywordKind::Bool) =>
 | 
				
			||||||
| 
						 | 
					@ -1081,7 +1080,7 @@ impl Parser<'_> {
 | 
				
			||||||
                                    expected: SyntaxKind::Integer,
 | 
					                                    expected: SyntaxKind::Integer,
 | 
				
			||||||
                                    found: unexpected.into_token(),
 | 
					                                    found: unexpected.into_token(),
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                return Err(err);
 | 
					                                return Err(err);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
| 
						 | 
					@ -1095,18 +1094,10 @@ impl Parser<'_> {
 | 
				
			||||||
                let close_bracket = tree.close;
 | 
					                let close_bracket = tree.close;
 | 
				
			||||||
                let inner = tree.tree?;
 | 
					                let inner = tree.tree?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Some((open_bracket, inner, close_bracket))
 | 
					                match inner {
 | 
				
			||||||
            }
 | 
					                    IndexingType::IntegerSize(size) => {
 | 
				
			||||||
            _ => None,
 | 
					                        let assignment = self
 | 
				
			||||||
        };
 | 
					                            .try_parse(|p| {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // read identifier
 | 
					 | 
				
			||||||
        self.stop_at_significant();
 | 
					 | 
				
			||||||
        let identifier = self.parse_identifier(handler)?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // TODO: allow assignment when map and array literals have been implemented
 | 
					 | 
				
			||||||
        let assignment = if index.is_none() {
 | 
					 | 
				
			||||||
            self.try_parse(|p| {
 | 
					 | 
				
			||||||
                                // read equals sign
 | 
					                                // read equals sign
 | 
				
			||||||
                                let equals = p.parse_punctuation('=', true, &VoidHandler)?;
 | 
					                                let equals = p.parse_punctuation('=', true, &VoidHandler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1115,13 +1106,8 @@ impl Parser<'_> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                Ok(VariableDeclarationAssignment { equals, expression })
 | 
					                                Ok(VariableDeclarationAssignment { equals, expression })
 | 
				
			||||||
                            })
 | 
					                            })
 | 
				
			||||||
            .ok()
 | 
					                            .ok();
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            None
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match index {
 | 
					 | 
				
			||||||
            Some((open_bracket, IndexingType::IntegerSize(size), close_bracket)) => {
 | 
					 | 
				
			||||||
                        Ok(VariableDeclaration::Array(ArrayVariableDeclaration {
 | 
					                        Ok(VariableDeclaration::Array(ArrayVariableDeclaration {
 | 
				
			||||||
                            variable_type,
 | 
					                            variable_type,
 | 
				
			||||||
                            identifier,
 | 
					                            identifier,
 | 
				
			||||||
| 
						 | 
					@ -1132,9 +1118,9 @@ impl Parser<'_> {
 | 
				
			||||||
                            annotations: VecDeque::new(),
 | 
					                            annotations: VecDeque::new(),
 | 
				
			||||||
                        }))
 | 
					                        }))
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
            Some((open_bracket, IndexingType::None, close_bracket)) => {
 | 
					                    IndexingType::None => match variable_type.keyword {
 | 
				
			||||||
                match variable_type.keyword {
 | 
					                        KeywordKind::Int => {
 | 
				
			||||||
                    KeywordKind::Int => Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
 | 
					                            Ok(VariableDeclaration::Score(ScoreVariableDeclaration {
 | 
				
			||||||
                                int_keyword: variable_type,
 | 
					                                int_keyword: variable_type,
 | 
				
			||||||
                                criteria: criteria_selection,
 | 
					                                criteria: criteria_selection,
 | 
				
			||||||
                                identifier,
 | 
					                                identifier,
 | 
				
			||||||
| 
						 | 
					@ -1142,7 +1128,8 @@ impl Parser<'_> {
 | 
				
			||||||
                                close_bracket,
 | 
					                                close_bracket,
 | 
				
			||||||
                                assignment: None,
 | 
					                                assignment: None,
 | 
				
			||||||
                                annotations: VecDeque::new(),
 | 
					                                annotations: VecDeque::new(),
 | 
				
			||||||
                    })),
 | 
					                            }))
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration {
 | 
					                        KeywordKind::Bool => Ok(VariableDeclaration::Tag(TagVariableDeclaration {
 | 
				
			||||||
                            bool_keyword: variable_type,
 | 
					                            bool_keyword: variable_type,
 | 
				
			||||||
                            identifier,
 | 
					                            identifier,
 | 
				
			||||||
| 
						 | 
					@ -1152,15 +1139,22 @@ impl Parser<'_> {
 | 
				
			||||||
                            annotations: VecDeque::new(),
 | 
					                            annotations: VecDeque::new(),
 | 
				
			||||||
                        })),
 | 
					                        })),
 | 
				
			||||||
                        _ => unreachable!(),
 | 
					                        _ => unreachable!(),
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            None => {
 | 
					            // SingleVariableDeclaration with Assignment
 | 
				
			||||||
                if matches!(variable_type.keyword, KeywordKind::Val) {
 | 
					            Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '=' => {
 | 
				
			||||||
 | 
					                self.forward();
 | 
				
			||||||
 | 
					                let equals = punc;
 | 
				
			||||||
 | 
					                let expression = self.parse_expression(handler)?;
 | 
				
			||||||
 | 
					                let assignment = VariableDeclarationAssignment { equals, expression };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if variable_type.keyword == KeywordKind::Val {
 | 
				
			||||||
                    Ok(VariableDeclaration::ComptimeValue(
 | 
					                    Ok(VariableDeclaration::ComptimeValue(
 | 
				
			||||||
                        ComptimeValueDeclaration {
 | 
					                        ComptimeValueDeclaration {
 | 
				
			||||||
                            val_keyword: variable_type,
 | 
					                            val_keyword: variable_type,
 | 
				
			||||||
                            identifier,
 | 
					                            identifier,
 | 
				
			||||||
                            assignment,
 | 
					                            assignment: Some(assignment),
 | 
				
			||||||
                            annotations: VecDeque::new(),
 | 
					                            annotations: VecDeque::new(),
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
                    ))
 | 
					                    ))
 | 
				
			||||||
| 
						 | 
					@ -1168,11 +1162,18 @@ impl Parser<'_> {
 | 
				
			||||||
                    Ok(VariableDeclaration::Single(SingleVariableDeclaration {
 | 
					                    Ok(VariableDeclaration::Single(SingleVariableDeclaration {
 | 
				
			||||||
                        variable_type,
 | 
					                        variable_type,
 | 
				
			||||||
                        identifier,
 | 
					                        identifier,
 | 
				
			||||||
                        assignment,
 | 
					                        assignment: Some(assignment),
 | 
				
			||||||
                        annotations: VecDeque::new(),
 | 
					                        annotations: VecDeque::new(),
 | 
				
			||||||
                    }))
 | 
					                    }))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            // SingleVariableDeclaration without Assignment
 | 
				
			||||||
 | 
					            _ => Ok(VariableDeclaration::Single(SingleVariableDeclaration {
 | 
				
			||||||
 | 
					                variable_type,
 | 
				
			||||||
 | 
					                identifier,
 | 
				
			||||||
 | 
					                assignment: None,
 | 
				
			||||||
 | 
					                annotations: VecDeque::new(),
 | 
				
			||||||
 | 
					            })),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,5 @@
 | 
				
			||||||
//! Execute block statement syntax tree.
 | 
					//! Execute block statement syntax tree.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#![expect(clippy::struct_field_names)]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use derive_more::From;
 | 
					use derive_more::From;
 | 
				
			||||||
use enum_as_inner::EnumAsInner;
 | 
					use enum_as_inner::EnumAsInner;
 | 
				
			||||||
use getset::Getters;
 | 
					use getset::Getters;
 | 
				
			||||||
| 
						 | 
					@ -826,7 +824,7 @@ impl Parser<'_> {
 | 
				
			||||||
                            expected: SyntaxKind::Punctuation('('),
 | 
					                            expected: SyntaxKind::Punctuation('('),
 | 
				
			||||||
                            found: unexpected.into_token(),
 | 
					                            found: unexpected.into_token(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }?;
 | 
					                }?;
 | 
				
			||||||
| 
						 | 
					@ -844,7 +842,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::ExecuteBlock,
 | 
					                    expected: SyntaxKind::ExecuteBlock,
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -880,7 +878,7 @@ impl Parser<'_> {
 | 
				
			||||||
                    expected: SyntaxKind::ExecuteBlockTail,
 | 
					                    expected: SyntaxKind::ExecuteBlockTail,
 | 
				
			||||||
                    found: unexpected.into_token(),
 | 
					                    found: unexpected.into_token(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,8 +104,6 @@ impl MissingFunctionDeclaration {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Display for MissingFunctionDeclaration {
 | 
					impl Display for MissingFunctionDeclaration {
 | 
				
			||||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
        use std::fmt::Write as _;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let message = format!(
 | 
					        let message = format!(
 | 
				
			||||||
            "no matching function declaration found for invocation of function `{}`",
 | 
					            "no matching function declaration found for invocation of function `{}`",
 | 
				
			||||||
            self.span.str()
 | 
					            self.span.str()
 | 
				
			||||||
| 
						 | 
					@ -120,7 +118,7 @@ impl Display for MissingFunctionDeclaration {
 | 
				
			||||||
                if i > 0 {
 | 
					                if i > 0 {
 | 
				
			||||||
                    message.push_str(", ");
 | 
					                    message.push_str(", ");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                let _ = write!(message, "`{}`", alternative.identifier_span.str());
 | 
					                message.push_str(&format!("`{}`", alternative.identifier_span.str()));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Some(message + "?")
 | 
					            Some(message + "?")
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
| 
						 | 
					@ -400,11 +398,6 @@ pub enum IllegalIndexingReason {
 | 
				
			||||||
        /// The length indexed object.
 | 
					        /// The length indexed object.
 | 
				
			||||||
        length: usize,
 | 
					        length: usize,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /// The index provided is invalid
 | 
					 | 
				
			||||||
    InvalidIndex {
 | 
					 | 
				
			||||||
        /// The invalid index
 | 
					 | 
				
			||||||
        index: Span,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Display for IllegalIndexingReason {
 | 
					impl Display for IllegalIndexingReason {
 | 
				
			||||||
| 
						 | 
					@ -428,9 +421,6 @@ impl Display for IllegalIndexingReason {
 | 
				
			||||||
                    "The index {index} is out of bounds for the expression with length {length}."
 | 
					                    "The index {index} is out of bounds for the expression with length {length}."
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Self::InvalidIndex { index } => {
 | 
					 | 
				
			||||||
                write!(f, "The index {index} is invalid.", index = index.str())
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -405,7 +405,7 @@ impl Primary {
 | 
				
			||||||
            Self::Lua(lua) => lua
 | 
					            Self::Lua(lua) => lua
 | 
				
			||||||
                .eval_comptime(scope, &VoidHandler)
 | 
					                .eval_comptime(scope, &VoidHandler)
 | 
				
			||||||
                .inspect_err(|err| {
 | 
					                .inspect_err(|err| {
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .map_err(|_| NotComptime {
 | 
					                .map_err(|_| NotComptime {
 | 
				
			||||||
                    expression: lua.span(),
 | 
					                    expression: lua.span(),
 | 
				
			||||||
| 
						 | 
					@ -1191,7 +1191,7 @@ impl Transpiler {
 | 
				
			||||||
                                    .into(),
 | 
					                                    .into(),
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        let prepare_cmd = Command::Raw(format!("tag {entity} remove {tag_name}"));
 | 
					                        let prepare_cmd = Command::Raw(format!("tag {entity} remove {tag_name}"));
 | 
				
			||||||
| 
						 | 
					@ -1225,18 +1225,7 @@ impl Transpiler {
 | 
				
			||||||
                .parent()
 | 
					                .parent()
 | 
				
			||||||
                .comptime_member_access(member_access, scope, handler)
 | 
					                .comptime_member_access(member_access, scope, handler)
 | 
				
			||||||
                .map_or_else(
 | 
					                .map_or_else(
 | 
				
			||||||
                    |_| {
 | 
					                    |_| todo!("implement non-comptime member access"),
 | 
				
			||||||
                        // TODO: implement non-comptime access
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let err = TranspileError::IllegalIndexing(IllegalIndexing {
 | 
					 | 
				
			||||||
                            expression: member_access.member().span(),
 | 
					 | 
				
			||||||
                            reason: IllegalIndexingReason::InvalidIndex {
 | 
					 | 
				
			||||||
                                index: member_access.member().span(),
 | 
					 | 
				
			||||||
                            },
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					 | 
				
			||||||
                        Err(err)
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    |value| self.store_comptime_value(&value, target, member_access, handler),
 | 
					                    |value| self.store_comptime_value(&value, target, member_access, handler),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
            Primary::Lua(lua) =>
 | 
					            Primary::Lua(lua) =>
 | 
				
			||||||
| 
						 | 
					@ -1248,7 +1237,7 @@ impl Transpiler {
 | 
				
			||||||
                    let err = TranspileError::MissingValue(MissingValue {
 | 
					                    let err = TranspileError::MissingValue(MissingValue {
 | 
				
			||||||
                        expression: lua.span(),
 | 
					                        expression: lua.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1273,7 +1262,7 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: target.value_type().into(),
 | 
					                        expected_type: target.value_type().into(),
 | 
				
			||||||
                        expression: primary.span(),
 | 
					                        expression: primary.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1337,7 +1326,7 @@ impl Transpiler {
 | 
				
			||||||
                            expression: prefix.span(),
 | 
					                            expression: prefix.span(),
 | 
				
			||||||
                            expected_type: target.value_type().into(),
 | 
					                            expected_type: target.value_type().into(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					@ -1433,7 +1422,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected_type: target.value_type().into(),
 | 
					                                expected_type: target.value_type().into(),
 | 
				
			||||||
                                expression: primary.span(),
 | 
					                                expression: primary.span(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }?;
 | 
					                    }?;
 | 
				
			||||||
| 
						 | 
					@ -1443,7 +1432,7 @@ impl Transpiler {
 | 
				
			||||||
                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
					                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
				
			||||||
                        identifier: ident.span.clone(),
 | 
					                        identifier: ident.span.clone(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1455,7 +1444,7 @@ impl Transpiler {
 | 
				
			||||||
                        reason: IllegalIndexingReason::NotIdentifier,
 | 
					                        reason: IllegalIndexingReason::NotIdentifier,
 | 
				
			||||||
                        expression: indexed.object().span(),
 | 
					                        expression: indexed.object().span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }?;
 | 
					                }?;
 | 
				
			||||||
                let variable = scope.get_variable(ident.span.str());
 | 
					                let variable = scope.get_variable(ident.span.str());
 | 
				
			||||||
| 
						 | 
					@ -1477,7 +1466,7 @@ impl Transpiler {
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    expression: indexed.index().span(),
 | 
					                                    expression: indexed.index().span(),
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                Err(err)
 | 
					                                Err(err)
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -1502,7 +1491,7 @@ impl Transpiler {
 | 
				
			||||||
                                        },
 | 
					                                        },
 | 
				
			||||||
                                        expression: indexed.index().span(),
 | 
					                                        expression: indexed.index().span(),
 | 
				
			||||||
                                    });
 | 
					                                    });
 | 
				
			||||||
                                    handler.receive(Box::new(err.clone()));
 | 
					                                    handler.receive(err.clone());
 | 
				
			||||||
                                    Err(err)
 | 
					                                    Err(err)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            } else {
 | 
					                            } else {
 | 
				
			||||||
| 
						 | 
					@ -1512,7 +1501,7 @@ impl Transpiler {
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    expression: indexed.index().span(),
 | 
					                                    expression: indexed.index().span(),
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                Err(err)
 | 
					                                Err(err)
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -1541,7 +1530,7 @@ impl Transpiler {
 | 
				
			||||||
                                        },
 | 
					                                        },
 | 
				
			||||||
                                        expression: indexed.index().span(),
 | 
					                                        expression: indexed.index().span(),
 | 
				
			||||||
                                    });
 | 
					                                    });
 | 
				
			||||||
                                    handler.receive(Box::new(err.clone()));
 | 
					                                    handler.receive(err.clone());
 | 
				
			||||||
                                    Err(err)
 | 
					                                    Err(err)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            } else {
 | 
					                            } else {
 | 
				
			||||||
| 
						 | 
					@ -1551,7 +1540,7 @@ impl Transpiler {
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    expression: indexed.index().span(),
 | 
					                                    expression: indexed.index().span(),
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                Err(err)
 | 
					                                Err(err)
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -1560,7 +1549,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected_type: target.value_type().into(),
 | 
					                                expected_type: target.value_type().into(),
 | 
				
			||||||
                                expression: primary.span(),
 | 
					                                expression: primary.span(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }?;
 | 
					                    }?;
 | 
				
			||||||
| 
						 | 
					@ -1570,7 +1559,7 @@ impl Transpiler {
 | 
				
			||||||
                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
					                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
				
			||||||
                        identifier: ident.span.clone(),
 | 
					                        identifier: ident.span.clone(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1647,7 +1636,7 @@ impl Transpiler {
 | 
				
			||||||
                    expected_type: ExpectedType::Boolean,
 | 
					                    expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                    expression: primary.span(),
 | 
					                    expression: primary.span(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Primary::StringLiteral(s) => Ok((
 | 
					            Primary::StringLiteral(s) => Ok((
 | 
				
			||||||
| 
						 | 
					@ -1670,7 +1659,7 @@ impl Transpiler {
 | 
				
			||||||
                            message: "Function calls as conditions do not support arguments."
 | 
					                            message: "Function calls as conditions do not support arguments."
 | 
				
			||||||
                                .into(),
 | 
					                                .into(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    let (func_location, _) = self.get_or_transpile_function(
 | 
					                    let (func_location, _) = self.get_or_transpile_function(
 | 
				
			||||||
| 
						 | 
					@ -1713,7 +1702,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected_type: ExpectedType::Boolean,
 | 
					                                expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                                expression: primary.span(),
 | 
					                                expression: primary.span(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -1721,7 +1710,7 @@ impl Transpiler {
 | 
				
			||||||
                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
					                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
				
			||||||
                        identifier: ident.span.clone(),
 | 
					                        identifier: ident.span.clone(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1736,7 +1725,7 @@ impl Transpiler {
 | 
				
			||||||
                        reason: IllegalIndexingReason::NotIdentifier,
 | 
					                        reason: IllegalIndexingReason::NotIdentifier,
 | 
				
			||||||
                        expression: indexed.object().span(),
 | 
					                        expression: indexed.object().span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }?;
 | 
					                }?;
 | 
				
			||||||
                #[expect(clippy::option_if_let_else)]
 | 
					                #[expect(clippy::option_if_let_else)]
 | 
				
			||||||
| 
						 | 
					@ -1770,7 +1759,7 @@ impl Transpiler {
 | 
				
			||||||
                                        },
 | 
					                                        },
 | 
				
			||||||
                                        expression: indexed.index().span(),
 | 
					                                        expression: indexed.index().span(),
 | 
				
			||||||
                                    });
 | 
					                                    });
 | 
				
			||||||
                                    handler.receive(Box::new(err.clone()));
 | 
					                                    handler.receive(err.clone());
 | 
				
			||||||
                                    Err(err)
 | 
					                                    Err(err)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            } else {
 | 
					                            } else {
 | 
				
			||||||
| 
						 | 
					@ -1780,7 +1769,7 @@ impl Transpiler {
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    expression: indexed.index().span(),
 | 
					                                    expression: indexed.index().span(),
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                Err(err)
 | 
					                                Err(err)
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -1789,7 +1778,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected_type: ExpectedType::Boolean,
 | 
					                                expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                                expression: primary.span(),
 | 
					                                expression: primary.span(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -1797,7 +1786,7 @@ impl Transpiler {
 | 
				
			||||||
                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
					                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
				
			||||||
                        identifier: ident.span.clone(),
 | 
					                        identifier: ident.span.clone(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1805,18 +1794,7 @@ impl Transpiler {
 | 
				
			||||||
                .parent()
 | 
					                .parent()
 | 
				
			||||||
                .comptime_member_access(member_access, scope, handler)
 | 
					                .comptime_member_access(member_access, scope, handler)
 | 
				
			||||||
                .map_or_else(
 | 
					                .map_or_else(
 | 
				
			||||||
                    |_| {
 | 
					                    |_| todo!("implement non-comptime member access"),
 | 
				
			||||||
                        // TODO: implement non-comptime access
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let err = TranspileError::IllegalIndexing(IllegalIndexing {
 | 
					 | 
				
			||||||
                            expression: member_access.member().span(),
 | 
					 | 
				
			||||||
                            reason: IllegalIndexingReason::InvalidIndex {
 | 
					 | 
				
			||||||
                                index: member_access.member().span(),
 | 
					 | 
				
			||||||
                            },
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					 | 
				
			||||||
                        Err(err)
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    |value| match value {
 | 
					                    |value| match value {
 | 
				
			||||||
                        ComptimeValue::Boolean(b) => {
 | 
					                        ComptimeValue::Boolean(b) => {
 | 
				
			||||||
                            Ok((Vec::new(), ExtendedCondition::Comptime(b)))
 | 
					                            Ok((Vec::new(), ExtendedCondition::Comptime(b)))
 | 
				
			||||||
| 
						 | 
					@ -1826,7 +1804,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected_type: ExpectedType::Boolean,
 | 
					                                expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                                expression: primary.span(),
 | 
					                                expression: primary.span(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        ComptimeValue::String(s) => Ok((
 | 
					                        ComptimeValue::String(s) => Ok((
 | 
				
			||||||
| 
						 | 
					@ -1882,7 +1860,7 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: ExpectedType::Boolean,
 | 
					                        expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                        expression: primary.span(),
 | 
					                        expression: primary.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -1903,7 +1881,7 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: ExpectedType::Boolean,
 | 
					                        expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                        expression: primary.span(),
 | 
					                        expression: primary.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -1933,7 +1911,7 @@ impl Transpiler {
 | 
				
			||||||
                    expected_type: ExpectedType::Boolean,
 | 
					                    expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                    expression: binary.span(),
 | 
					                    expression: binary.span(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -2022,7 +2000,7 @@ impl Transpiler {
 | 
				
			||||||
                    expected_type: ExpectedType::Boolean,
 | 
					                    expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                    expression: binary.span(),
 | 
					                    expression: binary.span(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                return Err(err);
 | 
					                return Err(err);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            DataLocation::Storage {
 | 
					            DataLocation::Storage {
 | 
				
			||||||
| 
						 | 
					@ -2049,7 +2027,7 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: ExpectedType::Boolean,
 | 
					                        expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                        expression: binary.span(),
 | 
					                        expression: binary.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    return Err(err);
 | 
					                    return Err(err);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -2195,7 +2173,7 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: ExpectedType::Boolean,
 | 
					                        expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                        expression: source.span(),
 | 
					                        expression: source.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                DataLocation::Storage {
 | 
					                DataLocation::Storage {
 | 
				
			||||||
| 
						 | 
					@ -2219,7 +2197,7 @@ impl Transpiler {
 | 
				
			||||||
                            expression: source.span(),
 | 
					                            expression: source.span(),
 | 
				
			||||||
                            expected_type: target.value_type().into(),
 | 
					                            expected_type: target.value_type().into(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -2245,7 +2223,7 @@ impl Transpiler {
 | 
				
			||||||
                            expression: source.span(),
 | 
					                            expression: source.span(),
 | 
				
			||||||
                            expected_type: target.value_type().into(),
 | 
					                            expected_type: target.value_type().into(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -2280,7 +2258,7 @@ impl Transpiler {
 | 
				
			||||||
                            expected_type: target.value_type().into(),
 | 
					                            expected_type: target.value_type().into(),
 | 
				
			||||||
                            expression: source.span(),
 | 
					                            expression: source.span(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -2316,7 +2294,7 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: ExpectedType::Boolean,
 | 
					                        expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                        expression: source.span(),
 | 
					                        expression: source.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    return Err(err);
 | 
					                    return Err(err);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ use super::{
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub enum TranspiledFunctionArguments {
 | 
					pub enum TranspiledFunctionArguments {
 | 
				
			||||||
    None,
 | 
					    None,
 | 
				
			||||||
    Static(BTreeMap<String, MacroString>, Vec<Command>),
 | 
					    Static(BTreeMap<String, MacroString>),
 | 
				
			||||||
    Dynamic(Vec<Command>),
 | 
					    Dynamic(Vec<Command>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,11 +59,11 @@ impl Transpiler {
 | 
				
			||||||
            .expect("called variable should be of type function");
 | 
					            .expect("called variable should be of type function");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let function_data = function.ok_or_else(|| {
 | 
					        let function_data = function.ok_or_else(|| {
 | 
				
			||||||
            let err = TranspileError::MissingFunctionDeclaration(
 | 
					            let error = TranspileError::MissingFunctionDeclaration(
 | 
				
			||||||
                MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
 | 
					                MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            handler.receive(Box::new(err.clone()));
 | 
					            handler.receive(error.clone());
 | 
				
			||||||
            err
 | 
					            error
 | 
				
			||||||
        })?;
 | 
					        })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let VariableData::Function {
 | 
					        let VariableData::Function {
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ impl Transpiler {
 | 
				
			||||||
                                        .to_string(),
 | 
					                                        .to_string(),
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                            );
 | 
					                            );
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            err
 | 
					                            err
 | 
				
			||||||
                        }),
 | 
					                        }),
 | 
				
			||||||
                    TranspileAnnotationValue::Map(_, span) => {
 | 
					                    TranspileAnnotationValue::Map(_, span) => {
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,7 @@ impl Transpiler {
 | 
				
			||||||
                                annotation: span.clone(),
 | 
					                                annotation: span.clone(),
 | 
				
			||||||
                                message: "Deobfuscate annotation cannot be a map.".to_string(),
 | 
					                                message: "Deobfuscate annotation cannot be a map.".to_string(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					@ -175,7 +175,7 @@ impl Transpiler {
 | 
				
			||||||
                    name: modified_name,
 | 
					                    name: modified_name,
 | 
				
			||||||
                    definition: identifier_span.clone(),
 | 
					                    definition: identifier_span.clone(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                return Err(err);
 | 
					                return Err(err);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,11 +193,11 @@ impl Transpiler {
 | 
				
			||||||
        let function_location = function_path
 | 
					        let function_location = function_path
 | 
				
			||||||
            .get()
 | 
					            .get()
 | 
				
			||||||
            .ok_or_else(|| {
 | 
					            .ok_or_else(|| {
 | 
				
			||||||
                let err = TranspileError::MissingFunctionDeclaration(
 | 
					                let error = TranspileError::MissingFunctionDeclaration(
 | 
				
			||||||
                    MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
 | 
					                    MissingFunctionDeclaration::from_scope(identifier_span.clone(), scope),
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(error.clone());
 | 
				
			||||||
                err
 | 
					                error
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .map(String::to_owned)?;
 | 
					            .map(String::to_owned)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,7 +258,7 @@ impl Transpiler {
 | 
				
			||||||
                    actual: arg_count,
 | 
					                    actual: arg_count,
 | 
				
			||||||
                    span: identifier_span.clone(),
 | 
					                    span: identifier_span.clone(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Some(arg_count) if arg_count > 0 => {
 | 
					            Some(arg_count) if arg_count > 0 => {
 | 
				
			||||||
| 
						 | 
					@ -283,7 +283,7 @@ impl Transpiler {
 | 
				
			||||||
                                Ok(val) => Ok(Parameter::Static(val.to_macro_string())),
 | 
					                                Ok(val) => Ok(Parameter::Static(val.to_macro_string())),
 | 
				
			||||||
                                Err(err) => {
 | 
					                                Err(err) => {
 | 
				
			||||||
                                    let err = TranspileError::NotComptime(err);
 | 
					                                    let err = TranspileError::NotComptime(err);
 | 
				
			||||||
                                    handler.receive(Box::new(err.clone()));
 | 
					                                    handler.receive(err.clone());
 | 
				
			||||||
                                    Err(err)
 | 
					                                    Err(err)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            })
 | 
					                            })
 | 
				
			||||||
| 
						 | 
					@ -305,7 +305,7 @@ impl Transpiler {
 | 
				
			||||||
                                let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
					                                let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
				
			||||||
                                    identifier: ident.span(),
 | 
					                                    identifier: ident.span(),
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                err
 | 
					                                err
 | 
				
			||||||
                            })?;
 | 
					                            })?;
 | 
				
			||||||
                            match var.as_ref() {
 | 
					                            match var.as_ref() {
 | 
				
			||||||
| 
						 | 
					@ -353,7 +353,7 @@ impl Transpiler {
 | 
				
			||||||
                                            ExpectedType::String,
 | 
					                                            ExpectedType::String,
 | 
				
			||||||
                                        ]),
 | 
					                                        ]),
 | 
				
			||||||
                                    });
 | 
					                                    });
 | 
				
			||||||
                                    handler.receive(Box::new(err.clone()));
 | 
					                                    handler.receive(err.clone());
 | 
				
			||||||
                                    Err(err)
 | 
					                                    Err(err)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
| 
						 | 
					@ -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 (require_dyn_params, mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold(
 | 
					                    let (mut setup_cmds, move_cmds, static_params) = parameters.clone().into_iter().zip(compiled_args).fold(
 | 
				
			||||||
                        (false, Vec::new(), Vec::new(), BTreeMap::new()),
 | 
					                        (Vec::new(), Vec::new(), BTreeMap::new()),
 | 
				
			||||||
                        |(mut require_dyn_params, mut acc_setup, mut acc_move, mut statics), (param, data)| {
 | 
					                        |(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,7 +455,6 @@ 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}")
 | 
				
			||||||
| 
						 | 
					@ -496,7 +495,6 @@ 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);
 | 
				
			||||||
| 
						 | 
					@ -526,15 +524,12 @@ impl Transpiler {
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        (require_dyn_params, acc_setup, acc_move, statics)},
 | 
					                        (acc_setup, acc_move, statics)},
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    if require_dyn_params {
 | 
					 | 
				
			||||||
                    let statics_len = static_params.len();
 | 
					                    let statics_len = static_params.len();
 | 
				
			||||||
                        let joined_statics = super::util::join_macro_strings(
 | 
					                    let joined_statics =
 | 
				
			||||||
                            static_params
 | 
					                        super::util::join_macro_strings(static_params.into_iter().enumerate().map(
 | 
				
			||||||
                                .into_iter()
 | 
					                            |(i, (k, v))| match v {
 | 
				
			||||||
                                .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 {
 | 
				
			||||||
| 
						 | 
					@ -543,10 +538,7 @@ impl Transpiler {
 | 
				
			||||||
                                    MacroString::String(s)
 | 
					                                    MacroString::String(s)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                MacroString::MacroString(mut parts) => {
 | 
					                                MacroString::MacroString(mut parts) => {
 | 
				
			||||||
                                        parts.insert(
 | 
					                                    parts.insert(0, MacroStringPart::String(format!(r#"{k}:""#)));
 | 
				
			||||||
                                            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(',');
 | 
				
			||||||
| 
						 | 
					@ -554,39 +546,28 @@ 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_{storage_suffix} {{{s}}}"
 | 
					                            r"data merge storage shulkerscript:function_arguments {{{s}}}"
 | 
				
			||||||
                        )),
 | 
					                        )),
 | 
				
			||||||
                            MacroString::MacroString(_) => {
 | 
					                        MacroString::MacroString(_) => Command::UsesMacro(
 | 
				
			||||||
                                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([
 | 
				
			||||||
                                        prefix,
 | 
					                                MacroString::String(
 | 
				
			||||||
 | 
					                                    "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()
 | 
				
			||||||
| 
						 | 
					@ -598,10 +579,7 @@ 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(
 | 
					                    Ok(TranspiledFunctionArguments::Static(function_args))
 | 
				
			||||||
                        function_args,
 | 
					 | 
				
			||||||
                        Vec::new(),
 | 
					 | 
				
			||||||
                    ))
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => Ok(TranspiledFunctionArguments::None),
 | 
					            _ => Ok(TranspiledFunctionArguments::None),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ fn print_function(
 | 
				
			||||||
                    Ok((false, cmd, value))
 | 
					                    Ok((false, cmd, value))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => Err(TranspileError::UnexpectedExpression(UnexpectedExpression(
 | 
					                _ => Err(TranspileError::UnexpectedExpression(UnexpectedExpression(
 | 
				
			||||||
                    Box::new(Expression::Primary(Primary::Identifier(ident.to_owned()))),
 | 
					                    Expression::Primary(Primary::Identifier(ident.to_owned())),
 | 
				
			||||||
                ))),
 | 
					                ))),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ mod enabled {
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.add_globals(&lua, scope)
 | 
					            self.add_globals(&lua, scope)
 | 
				
			||||||
                .inspect_err(|err| handler.receive(Box::new(err.clone())))?;
 | 
					                .inspect_err(|err| handler.receive(err.clone()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let res = lua
 | 
					            let res = lua
 | 
				
			||||||
                .load(self.code())
 | 
					                .load(self.code())
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ mod enabled {
 | 
				
			||||||
                .map_err(|err| {
 | 
					                .map_err(|err| {
 | 
				
			||||||
                    let err =
 | 
					                    let err =
 | 
				
			||||||
                        TranspileError::from(LuaRuntimeError::from_lua_err(&err, self.span()));
 | 
					                        TranspileError::from(LuaRuntimeError::from_lua_err(&err, self.span()));
 | 
				
			||||||
                    handler.receive(crate::Error::from(Box::new(err.clone())));
 | 
					                    handler.receive(crate::Error::from(err.clone()));
 | 
				
			||||||
                    err
 | 
					                    err
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -329,7 +329,7 @@ mod enabled {
 | 
				
			||||||
                            code_block: self.span(),
 | 
					                            code_block: self.span(),
 | 
				
			||||||
                            error_message: "return table must contain non-nil 'value'".to_string(),
 | 
					                            error_message: "return table must contain non-nil 'value'".to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Ok(value) => {
 | 
					                    Ok(value) => {
 | 
				
			||||||
| 
						 | 
					@ -348,7 +348,7 @@ mod enabled {
 | 
				
			||||||
                                                    expression: self.span(),
 | 
					                                                    expression: self.span(),
 | 
				
			||||||
                                                    expected_type: ExpectedType::Boolean,
 | 
					                                                    expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                                                });
 | 
					                                                });
 | 
				
			||||||
                                            handler.receive(Box::new(err.clone()));
 | 
					                                            handler.receive(err.clone());
 | 
				
			||||||
                                            Err(err)
 | 
					                                            Err(err)
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
| 
						 | 
					@ -358,7 +358,7 @@ mod enabled {
 | 
				
			||||||
                                                expression: self.span(),
 | 
					                                                expression: self.span(),
 | 
				
			||||||
                                                expected_type: ExpectedType::Boolean,
 | 
					                                                expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                                            });
 | 
					                                            });
 | 
				
			||||||
                                        handler.receive(Box::new(err.clone()));
 | 
					                                        handler.receive(err.clone());
 | 
				
			||||||
                                        Err(err)
 | 
					                                        Err(err)
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                }?;
 | 
					                                }?;
 | 
				
			||||||
| 
						 | 
					@ -380,7 +380,7 @@ mod enabled {
 | 
				
			||||||
                            &err,
 | 
					                            &err,
 | 
				
			||||||
                            self.span(),
 | 
					                            self.span(),
 | 
				
			||||||
                        ));
 | 
					                        ));
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					@ -393,7 +393,7 @@ mod enabled {
 | 
				
			||||||
                        code_block: self.span(),
 | 
					                        code_block: self.span(),
 | 
				
			||||||
                        error_message: format!("invalid return type {}", value.type_name()),
 | 
					                        error_message: format!("invalid return type {}", value.type_name()),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,12 +196,13 @@ impl Transpiler {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TranspileAnnotationValue::Expression(_, span)
 | 
					                TranspileAnnotationValue::Expression(_, span)
 | 
				
			||||||
                | TranspileAnnotationValue::Map(_, span) => {
 | 
					                | TranspileAnnotationValue::Map(_, span) => {
 | 
				
			||||||
                    let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                    let error =
 | 
				
			||||||
 | 
					                        TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                            annotation: span.clone(),
 | 
					                            annotation: span.clone(),
 | 
				
			||||||
                            message: "uninstall annotation must not have a value".to_string(),
 | 
					                            message: "uninstall annotation must not have a value".to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(error)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .collect::<TranspileResult<Vec<_>>>()?;
 | 
					            .collect::<TranspileResult<Vec<_>>>()?;
 | 
				
			||||||
| 
						 | 
					@ -272,7 +273,7 @@ impl Transpiler {
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    .collect();
 | 
					                    .collect();
 | 
				
			||||||
                let function_data = FunctionData {
 | 
					                let function_data = FunctionData {
 | 
				
			||||||
                    namespace: namespace.name().str_content().to_string(),
 | 
					                    namespace: namespace.namespace_name().str_content().to_string(),
 | 
				
			||||||
                    identifier_span: identifier_span.clone(),
 | 
					                    identifier_span: identifier_span.clone(),
 | 
				
			||||||
                    parameters: function
 | 
					                    parameters: function
 | 
				
			||||||
                        .parameters()
 | 
					                        .parameters()
 | 
				
			||||||
| 
						 | 
					@ -317,7 +318,9 @@ impl Transpiler {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Declaration::Tag(tag) => {
 | 
					            Declaration::Tag(tag) => {
 | 
				
			||||||
                let namespace = self.datapack.namespace_mut(namespace.name().str_content());
 | 
					                let namespace = self
 | 
				
			||||||
 | 
					                    .datapack
 | 
				
			||||||
 | 
					                    .namespace_mut(namespace.namespace_name().str_content());
 | 
				
			||||||
                let sb_tag = namespace.tag_mut(tag.name().str_content(), tag.tag_type());
 | 
					                let sb_tag = namespace.tag_mut(tag.name().str_content(), tag.tag_type());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if let Some(list) = &tag.entries().list {
 | 
					                if let Some(list) = &tag.entries().list {
 | 
				
			||||||
| 
						 | 
					@ -341,7 +344,7 @@ impl Transpiler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                self.setup_cmds.extend(setup_variable_cmds);
 | 
					                self.setup_cmds.extend(setup_variable_cmds);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -412,11 +415,11 @@ impl Transpiler {
 | 
				
			||||||
                        self.transpile_run_expression(prefix.operand(), scope, handler)
 | 
					                        self.transpile_run_expression(prefix.operand(), scope, handler)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    unexpected => {
 | 
					                    unexpected => {
 | 
				
			||||||
                        let err = TranspileError::UnexpectedExpression(UnexpectedExpression(
 | 
					                        let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
 | 
				
			||||||
                            Box::new(unexpected.clone()),
 | 
					                            unexpected.clone(),
 | 
				
			||||||
                        ));
 | 
					                        ));
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(error.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(error)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                SemicolonStatement::VariableDeclaration(decl) => self
 | 
					                SemicolonStatement::VariableDeclaration(decl) => self
 | 
				
			||||||
| 
						 | 
					@ -492,11 +495,11 @@ impl Transpiler {
 | 
				
			||||||
                                read_only: _,
 | 
					                                read_only: _,
 | 
				
			||||||
                            } => value.read().unwrap().as_ref().map_or_else(
 | 
					                            } => value.read().unwrap().as_ref().map_or_else(
 | 
				
			||||||
                                || {
 | 
					                                || {
 | 
				
			||||||
                                    let err = TranspileError::MissingValue(MissingValue {
 | 
					                                    let error = TranspileError::MissingValue(MissingValue {
 | 
				
			||||||
                                        expression: ident.span.clone(),
 | 
					                                        expression: ident.span.clone(),
 | 
				
			||||||
                                    });
 | 
					                                    });
 | 
				
			||||||
                                    handler.receive(Box::new(err.clone()));
 | 
					                                    handler.receive(error.clone());
 | 
				
			||||||
                                    Err(err)
 | 
					                                    Err(error)
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                                |val| {
 | 
					                                |val| {
 | 
				
			||||||
                                    let cmd = val.to_string_no_macro().map_or_else(
 | 
					                                    let cmd = val.to_string_no_macro().map_or_else(
 | 
				
			||||||
| 
						 | 
					@ -529,21 +532,20 @@ impl Transpiler {
 | 
				
			||||||
                                )))),
 | 
					                                )))),
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            _ => {
 | 
					                            _ => {
 | 
				
			||||||
                                let err = TranspileError::UnexpectedExpression(
 | 
					                                let error =
 | 
				
			||||||
                                    UnexpectedExpression(Box::new(Expression::Primary(
 | 
					                                    TranspileError::UnexpectedExpression(UnexpectedExpression(
 | 
				
			||||||
                                        Primary::Identifier(ident.clone()),
 | 
					                                        Expression::Primary(Primary::Identifier(ident.clone())),
 | 
				
			||||||
                                    ))),
 | 
					                                    ));
 | 
				
			||||||
                                );
 | 
					                                handler.receive(error.clone());
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                return Err(error);
 | 
				
			||||||
                                return Err(err);
 | 
					 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
					                        let error = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
				
			||||||
                            identifier: ident.span.clone(),
 | 
					                            identifier: ident.span.clone(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(error.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(error);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
| 
						 | 
					@ -588,11 +590,11 @@ impl Transpiler {
 | 
				
			||||||
                    read_only: _,
 | 
					                    read_only: _,
 | 
				
			||||||
                }) => value.read().unwrap().as_ref().map_or_else(
 | 
					                }) => value.read().unwrap().as_ref().map_or_else(
 | 
				
			||||||
                    || {
 | 
					                    || {
 | 
				
			||||||
                        let err = TranspileError::MissingValue(MissingValue {
 | 
					                        let error = TranspileError::MissingValue(MissingValue {
 | 
				
			||||||
                            expression: ident.span.clone(),
 | 
					                            expression: ident.span.clone(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(error.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(error)
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    |val| {
 | 
					                    |val| {
 | 
				
			||||||
                        let cmd = val.to_string_no_macro().map_or_else(
 | 
					                        let cmd = val.to_string_no_macro().map_or_else(
 | 
				
			||||||
| 
						 | 
					@ -603,18 +605,18 @@ impl Transpiler {
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                Some(_) => {
 | 
					                Some(_) => {
 | 
				
			||||||
                    let err = TranspileError::UnexpectedExpression(UnexpectedExpression(Box::new(
 | 
					                    let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
 | 
				
			||||||
                        Expression::Primary(expression.clone()),
 | 
					                        Expression::Primary(expression.clone()),
 | 
				
			||||||
                    )));
 | 
					                    ));
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(error)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                None => {
 | 
					                None => {
 | 
				
			||||||
                    let err = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
					                    let error = TranspileError::UnknownIdentifier(UnknownIdentifier {
 | 
				
			||||||
                        identifier: ident.span.clone(),
 | 
					                        identifier: ident.span.clone(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(error)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -623,11 +625,11 @@ impl Transpiler {
 | 
				
			||||||
            | Primary::Prefix(_)
 | 
					            | Primary::Prefix(_)
 | 
				
			||||||
            | Primary::Indexed(_)
 | 
					            | Primary::Indexed(_)
 | 
				
			||||||
            | Primary::MemberAccess(_) => {
 | 
					            | Primary::MemberAccess(_) => {
 | 
				
			||||||
                let err = TranspileError::UnexpectedExpression(UnexpectedExpression(Box::new(
 | 
					                let error = TranspileError::UnexpectedExpression(UnexpectedExpression(
 | 
				
			||||||
                    Expression::Primary(expression.clone()),
 | 
					                    Expression::Primary(expression.clone()),
 | 
				
			||||||
                )));
 | 
					                ));
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(error.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(error)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Primary::StringLiteral(string) => {
 | 
					            Primary::StringLiteral(string) => {
 | 
				
			||||||
                Ok(vec![Command::Raw(string.str_content().to_string())])
 | 
					                Ok(vec![Command::Raw(string.str_content().to_string())])
 | 
				
			||||||
| 
						 | 
					@ -641,14 +643,14 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: ExpectedType::String,
 | 
					                        expected_type: ExpectedType::String,
 | 
				
			||||||
                        expression: code.span(),
 | 
					                        expression: code.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Err(_) => {
 | 
					                Err(_) => {
 | 
				
			||||||
                    let err = TranspileError::MissingValue(MissingValue {
 | 
					                    let err = TranspileError::MissingValue(MissingValue {
 | 
				
			||||||
                        expression: code.span(),
 | 
					                        expression: code.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -665,12 +667,12 @@ impl Transpiler {
 | 
				
			||||||
                            expression: bin.span(),
 | 
					                            expression: bin.span(),
 | 
				
			||||||
                            expected_type: ExpectedType::String,
 | 
					                            expected_type: ExpectedType::String,
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Err(not_comptime) => {
 | 
					                    Err(not_comptime) => {
 | 
				
			||||||
                        let err = TranspileError::NotComptime(not_comptime);
 | 
					                        let err = TranspileError::NotComptime(not_comptime);
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					@ -692,7 +694,7 @@ impl Transpiler {
 | 
				
			||||||
            scope.get_variable(func.identifier().span.str()).as_deref()
 | 
					            scope.get_variable(func.identifier().span.str()).as_deref()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            implementation(self, scope, func).inspect_err(|err| {
 | 
					            implementation(self, scope, func).inspect_err(|err| {
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            let (location, arguments) = self.get_or_transpile_function(
 | 
					            let (location, arguments) = self.get_or_transpile_function(
 | 
				
			||||||
| 
						 | 
					@ -703,12 +705,8 @@ impl Transpiler {
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
            let mut function_call = format!("function {location}");
 | 
					            let mut function_call = format!("function {location}");
 | 
				
			||||||
            match arguments {
 | 
					            match arguments {
 | 
				
			||||||
                TranspiledFunctionArguments::Static(arguments, mut setup_cmds) => {
 | 
					                TranspiledFunctionArguments::Static(arguments) => {
 | 
				
			||||||
                    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}""#,
 | 
				
			||||||
| 
						 | 
					@ -721,9 +719,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(
 | 
					                                MacroStringPart::String(s) => {
 | 
				
			||||||
                                        crate::util::escape_str(&s).to_string(),
 | 
					                                    MacroStringPart::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())))
 | 
				
			||||||
| 
						 | 
					@ -732,7 +730,7 @@ impl Transpiler {
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    let arguments = super::util::join_macro_strings(arguments_iter);
 | 
					                    let arguments = super::util::join_macro_strings(arguments_iter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        match arguments {
 | 
					                    let cmd = 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)
 | 
				
			||||||
| 
						 | 
					@ -743,21 +741,12 @@ 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())
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    setup_cmds.push(cmd);
 | 
					                    Ok(vec![cmd])
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    Ok(setup_cmds)
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TranspiledFunctionArguments::Dynamic(mut cmds) => {
 | 
					                TranspiledFunctionArguments::Dynamic(mut cmds) => {
 | 
				
			||||||
                    use std::fmt::Write as _;
 | 
					                    function_call.push_str(" with storage shulkerscript:function_arguments");
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    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)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ impl MacroString {
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// # Errors
 | 
					    /// # Errors
 | 
				
			||||||
    /// - If the macro string contains macros
 | 
					    /// - If the macro string contains macros
 | 
				
			||||||
    pub fn as_str(&self) -> Result<std::borrow::Cow<'_, str>, &[MacroStringPart]> {
 | 
					    pub fn as_str(&self) -> Result<std::borrow::Cow<str>, &[MacroStringPart]> {
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            Self::String(s) => Ok(std::borrow::Cow::Borrowed(s)),
 | 
					            Self::String(s) => Ok(std::borrow::Cow::Borrowed(s)),
 | 
				
			||||||
            Self::MacroString(parts) if self.contains_macros() => Err(parts),
 | 
					            Self::MacroString(parts) if self.contains_macros() => Err(parts),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -308,7 +308,7 @@ impl Transpiler {
 | 
				
			||||||
                            .comptime_eval(scope, handler)
 | 
					                            .comptime_eval(scope, handler)
 | 
				
			||||||
                            .map_err(|err| {
 | 
					                            .map_err(|err| {
 | 
				
			||||||
                                let err = TranspileError::NotComptime(err);
 | 
					                                let err = TranspileError::NotComptime(err);
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                err
 | 
					                                err
 | 
				
			||||||
                            })?,
 | 
					                            })?,
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
| 
						 | 
					@ -569,7 +569,7 @@ impl Transpiler {
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                            expression: expression.span(),
 | 
					                            expression: expression.span(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Some(_) => {
 | 
					                    Some(_) => {
 | 
				
			||||||
| 
						 | 
					@ -579,7 +579,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected: ExpectedType::String,
 | 
					                                expected: ExpectedType::String,
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    None => {
 | 
					                    None => {
 | 
				
			||||||
| 
						 | 
					@ -588,7 +588,7 @@ impl Transpiler {
 | 
				
			||||||
                            identifier: identifier.span(),
 | 
					                            identifier: identifier.span(),
 | 
				
			||||||
                            message: "Cannot assign to a scoreboard without indexing".to_string(),
 | 
					                            message: "Cannot assign to a scoreboard without indexing".to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					@ -617,7 +617,7 @@ impl Transpiler {
 | 
				
			||||||
                                        length: targets.len(),
 | 
					                                        length: targets.len(),
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                return Err(err);
 | 
					                                return Err(err);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -628,7 +628,7 @@ impl Transpiler {
 | 
				
			||||||
                                    expected: ExpectedType::Integer,
 | 
					                                    expected: ExpectedType::Integer,
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            return Err(err);
 | 
					                            return Err(err);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        None => {
 | 
					                        None => {
 | 
				
			||||||
| 
						 | 
					@ -637,7 +637,7 @@ impl Transpiler {
 | 
				
			||||||
                                identifier: identifier.span(),
 | 
					                                identifier: identifier.span(),
 | 
				
			||||||
                                message: "Cannot assign to an array without indexing".to_string(),
 | 
					                                message: "Cannot assign to an array without indexing".to_string(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            return Err(err);
 | 
					                            return Err(err);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -671,7 +671,7 @@ impl Transpiler {
 | 
				
			||||||
                                        length: paths.len(),
 | 
					                                        length: paths.len(),
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(err.clone());
 | 
				
			||||||
                                return Err(err);
 | 
					                                return Err(err);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -682,7 +682,7 @@ impl Transpiler {
 | 
				
			||||||
                                    expected: ExpectedType::Integer,
 | 
					                                    expected: ExpectedType::Integer,
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            return Err(err);
 | 
					                            return Err(err);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        None => {
 | 
					                        None => {
 | 
				
			||||||
| 
						 | 
					@ -691,7 +691,7 @@ impl Transpiler {
 | 
				
			||||||
                                identifier: identifier.span(),
 | 
					                                identifier: identifier.span(),
 | 
				
			||||||
                                message: "Cannot assign to an array without indexing".to_string(),
 | 
					                                message: "Cannot assign to an array without indexing".to_string(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            return Err(err);
 | 
					                            return Err(err);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -709,7 +709,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected: ExpectedType::String,
 | 
					                                expected: ExpectedType::String,
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Some(_) => {
 | 
					                    Some(_) => {
 | 
				
			||||||
| 
						 | 
					@ -719,7 +719,7 @@ impl Transpiler {
 | 
				
			||||||
                                expected: ExpectedType::String,
 | 
					                                expected: ExpectedType::String,
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    None => {
 | 
					                    None => {
 | 
				
			||||||
| 
						 | 
					@ -728,7 +728,7 @@ impl Transpiler {
 | 
				
			||||||
                            identifier: identifier.span(),
 | 
					                            identifier: identifier.span(),
 | 
				
			||||||
                            message: "Cannot assign to a tag without indexing".to_string(),
 | 
					                            message: "Cannot assign to a tag without indexing".to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					@ -738,13 +738,13 @@ impl Transpiler {
 | 
				
			||||||
                            identifier: identifier.span(),
 | 
					                            identifier: identifier.span(),
 | 
				
			||||||
                            message: "Cannot assign to a read-only value.".to_string(),
 | 
					                            message: "Cannot assign to a read-only value.".to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    let comptime_value =
 | 
					                    let comptime_value =
 | 
				
			||||||
                        expression.comptime_eval(scope, handler).map_err(|err| {
 | 
					                        expression.comptime_eval(scope, handler).map_err(|err| {
 | 
				
			||||||
                            let err = TranspileError::NotComptime(err);
 | 
					                            let err = TranspileError::NotComptime(err);
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            err
 | 
					                            err
 | 
				
			||||||
                        })?;
 | 
					                        })?;
 | 
				
			||||||
                    *value.write().unwrap() = Some(comptime_value);
 | 
					                    *value.write().unwrap() = Some(comptime_value);
 | 
				
			||||||
| 
						 | 
					@ -765,7 +765,7 @@ impl Transpiler {
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }?;
 | 
					            }?;
 | 
				
			||||||
| 
						 | 
					@ -775,7 +775,7 @@ impl Transpiler {
 | 
				
			||||||
                identifier: identifier.span(),
 | 
					                identifier: identifier.span(),
 | 
				
			||||||
                message: "Variable does not exist.".to_string(),
 | 
					                message: "Variable does not exist.".to_string(),
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            handler.receive(Box::new(err.clone()));
 | 
					            handler.receive(err.clone());
 | 
				
			||||||
            Err(err)
 | 
					            Err(err)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -796,12 +796,12 @@ impl Transpiler {
 | 
				
			||||||
        let deobfuscate_annotation = deobfuscate_annotations.next();
 | 
					        let deobfuscate_annotation = deobfuscate_annotations.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(duplicate) = deobfuscate_annotations.next() {
 | 
					        if let Some(duplicate) = deobfuscate_annotations.next() {
 | 
				
			||||||
            let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					            let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                annotation: duplicate.span(),
 | 
					                annotation: duplicate.span(),
 | 
				
			||||||
                message: "Multiple deobfuscate annotations are not allowed.".to_string(),
 | 
					                message: "Multiple deobfuscate annotations are not allowed.".to_string(),
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            handler.receive(Box::new(err.clone()));
 | 
					            handler.receive(error.clone());
 | 
				
			||||||
            return Err(err);
 | 
					            return Err(error);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if let Some(deobfuscate_annotation) = deobfuscate_annotation {
 | 
					        if let Some(deobfuscate_annotation) = deobfuscate_annotation {
 | 
				
			||||||
            let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
 | 
					            let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
 | 
				
			||||||
| 
						 | 
					@ -818,32 +818,33 @@ impl Transpiler {
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // TODO: change invalid criteria if boolean
 | 
					                        // TODO: change invalid criteria if boolean
 | 
				
			||||||
                        if !crate::util::is_valid_scoreboard_objective_name(&name_eval) {
 | 
					                        if !crate::util::is_valid_scoreboard_objective_name(&name_eval) {
 | 
				
			||||||
                            let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                            let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                                                    annotation: deobfuscate_annotation.span(),
 | 
					                                                    annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                                                    message: "Deobfuscate annotation must be a valid scoreboard objective name.".to_string()
 | 
					                                                    message: "Deobfuscate annotation must be a valid scoreboard objective name.".to_string()
 | 
				
			||||||
                                                });
 | 
					                                                });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(error.clone());
 | 
				
			||||||
                            return Err(err);
 | 
					                            return Err(error);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        Ok(name_eval)
 | 
					                        Ok(name_eval)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                        let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                                                annotation: deobfuscate_annotation.span(),
 | 
					                                                annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                                                message: "Deobfuscate annotation could not have been evaluated at compile time.".to_string()
 | 
					                                                message: "Deobfuscate annotation could not have been evaluated at compile time.".to_string()
 | 
				
			||||||
                                            });
 | 
					                                            });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(error.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(error)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TranspileAnnotationValue::None(_) => Ok(identifier.span.str().to_string()),
 | 
					                TranspileAnnotationValue::None(_) => Ok(identifier.span.str().to_string()),
 | 
				
			||||||
                TranspileAnnotationValue::Map(_, _) => {
 | 
					                TranspileAnnotationValue::Map(_, _) => {
 | 
				
			||||||
                    let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                    let error =
 | 
				
			||||||
 | 
					                        TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                            annotation: deobfuscate_annotation.span(),
 | 
					                            annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                            message: "Deobfuscate annotation must have no value or must be string."
 | 
					                            message: "Deobfuscate annotation must have no value or must be string."
 | 
				
			||||||
                                .to_string(),
 | 
					                                .to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(error)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
| 
						 | 
					@ -880,12 +881,12 @@ impl Transpiler {
 | 
				
			||||||
        let deobfuscate_annotation = deobfuscate_annotations.next();
 | 
					        let deobfuscate_annotation = deobfuscate_annotations.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(duplicate) = deobfuscate_annotations.next() {
 | 
					        if let Some(duplicate) = deobfuscate_annotations.next() {
 | 
				
			||||||
            let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					            let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                annotation: duplicate.span(),
 | 
					                annotation: duplicate.span(),
 | 
				
			||||||
                message: "Multiple deobfuscate annotations are not allowed.".to_string(),
 | 
					                message: "Multiple deobfuscate annotations are not allowed.".to_string(),
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            handler.receive(Box::new(err.clone()));
 | 
					            handler.receive(error.clone());
 | 
				
			||||||
            return Err(err);
 | 
					            return Err(error);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if let Some(deobfuscate_annotation) = deobfuscate_annotation {
 | 
					        if let Some(deobfuscate_annotation) = deobfuscate_annotation {
 | 
				
			||||||
            let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
 | 
					            let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
 | 
				
			||||||
| 
						 | 
					@ -895,13 +896,14 @@ impl Transpiler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            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 err = 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(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    return Err(err);
 | 
					                    return Err(error);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if let (Some(name), Some(target)) = (map.get("name"), map.get("target")) {
 | 
					                if let (Some(name), Some(target)) = (map.get("name"), map.get("target")) {
 | 
				
			||||||
                    if let (
 | 
					                    if let (
 | 
				
			||||||
| 
						 | 
					@ -921,54 +923,56 @@ impl Transpiler {
 | 
				
			||||||
                        ) {
 | 
					                        ) {
 | 
				
			||||||
                            // TODO: change invalid criteria if boolean
 | 
					                            // TODO: change invalid criteria if boolean
 | 
				
			||||||
                            if !crate::util::is_valid_scoreboard_objective_name(&name_eval) {
 | 
					                            if !crate::util::is_valid_scoreboard_objective_name(&name_eval) {
 | 
				
			||||||
                                let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                                let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                                            annotation: deobfuscate_annotation.span(),
 | 
					                                            annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                                            message: "Deobfuscate annotation 'name' must be a valid scoreboard objective name.".to_string()
 | 
					                                            message: "Deobfuscate annotation 'name' must be a valid scoreboard objective name.".to_string()
 | 
				
			||||||
                                        });
 | 
					                                        });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(error.clone());
 | 
				
			||||||
                                return Err(err);
 | 
					                                return Err(error);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            if !crate::util::is_valid_scoreboard_target(&target_eval) {
 | 
					                            if !crate::util::is_valid_scoreboard_target(&target_eval) {
 | 
				
			||||||
                                let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                                let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                                            annotation: deobfuscate_annotation.span(),
 | 
					                                            annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                                            message: "Deobfuscate annotation 'target' must be a valid scoreboard player name.".to_string()
 | 
					                                            message: "Deobfuscate annotation 'target' must be a valid scoreboard player name.".to_string()
 | 
				
			||||||
                                        });
 | 
					                                        });
 | 
				
			||||||
                                handler.receive(Box::new(err.clone()));
 | 
					                                handler.receive(error.clone());
 | 
				
			||||||
                                return Err(err);
 | 
					                                return Err(error);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            Ok((name_eval, target_eval))
 | 
					                            Ok((name_eval, target_eval))
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                            let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                                        annotation: deobfuscate_annotation.span(),
 | 
					                                        annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                                        message: "Deobfuscate annotation 'name' or 'target' could not have been evaluated at compile time.".to_string()
 | 
					                                        message: "Deobfuscate annotation 'name' or 'target' could not have been evaluated at compile time.".to_string()
 | 
				
			||||||
                                    });
 | 
					                                    });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(error.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(error)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                        let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                                    annotation: deobfuscate_annotation.span(),
 | 
					                                    annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                                    message: "Deobfuscate annotation 'name' and 'target' must be compile time expressions.".to_string()
 | 
					                                    message: "Deobfuscate annotation 'name' and 'target' must be compile time expressions.".to_string()
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(error.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(error)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    let err = 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(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(error)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                    annotation: deobfuscate_annotation.span(),
 | 
					                    annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                    message: "Deobfuscate annotation must be a map.".to_string(),
 | 
					                    message: "Deobfuscate annotation must be a map.".to_string(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(error.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(error)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            let hashed = md5::hash(program_identifier).to_hex_lowercase();
 | 
					            let hashed = md5::hash(program_identifier).to_hex_lowercase();
 | 
				
			||||||
| 
						 | 
					@ -1013,12 +1017,12 @@ impl Transpiler {
 | 
				
			||||||
        let deobfuscate_annotation = deobfuscate_annotations.next();
 | 
					        let deobfuscate_annotation = deobfuscate_annotations.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(duplicate) = deobfuscate_annotations.next() {
 | 
					        if let Some(duplicate) = deobfuscate_annotations.next() {
 | 
				
			||||||
            let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					            let error = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                annotation: duplicate.span(),
 | 
					                annotation: duplicate.span(),
 | 
				
			||||||
                message: "Multiple deobfuscate annotations are not allowed.".to_string(),
 | 
					                message: "Multiple deobfuscate annotations are not allowed.".to_string(),
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            handler.receive(Box::new(err.clone()));
 | 
					            handler.receive(error.clone());
 | 
				
			||||||
            return Err(err);
 | 
					            return Err(error);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if let Some(deobfuscate_annotation) = deobfuscate_annotation {
 | 
					        if let Some(deobfuscate_annotation) = deobfuscate_annotation {
 | 
				
			||||||
            let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
 | 
					            let deobfuscate_annotation_value = TranspileAnnotationValue::from_annotation_value(
 | 
				
			||||||
| 
						 | 
					@ -1044,21 +1048,24 @@ impl Transpiler {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TranspileAnnotationValue::Map(map, _) => {
 | 
					                TranspileAnnotationValue::Map(map, _) => {
 | 
				
			||||||
                    // TODO: implement when map deobfuscate annotation is implemented
 | 
					                    // TODO: implement when map deobfuscate annotation is implemented
 | 
				
			||||||
                    let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                    let error =
 | 
				
			||||||
 | 
					                        TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                            annotation: deobfuscate_annotation.span(),
 | 
					                            annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                            message: "Deobfuscate annotation value must be a string or none."
 | 
					                            message: "Deobfuscate annotation value must be a string or none."
 | 
				
			||||||
                                .to_string(),
 | 
					                                .to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(error)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TranspileAnnotationValue::Expression(_, _) => {
 | 
					                TranspileAnnotationValue::Expression(_, _) => {
 | 
				
			||||||
                    let err = TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
					                    let error =
 | 
				
			||||||
 | 
					                        TranspileError::IllegalAnnotationContent(IllegalAnnotationContent {
 | 
				
			||||||
                            annotation: deobfuscate_annotation.span(),
 | 
					                            annotation: deobfuscate_annotation.span(),
 | 
				
			||||||
                        message: "Deobfuscate annotation value must be a map or none.".to_string(),
 | 
					                            message: "Deobfuscate annotation value must be a map or none."
 | 
				
			||||||
 | 
					                                .to_string(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(error.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(error)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
| 
						 | 
					@ -1161,7 +1168,7 @@ impl Transpiler {
 | 
				
			||||||
                                expression: expression.span(),
 | 
					                                expression: expression.span(),
 | 
				
			||||||
                                expected_type: to.value_type().into(),
 | 
					                                expected_type: to.value_type().into(),
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
                            handler.receive(Box::new(err.clone()));
 | 
					                            handler.receive(err.clone());
 | 
				
			||||||
                            Err(err)
 | 
					                            Err(err)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -1212,7 +1219,7 @@ impl Transpiler {
 | 
				
			||||||
                            expression: expression.span(),
 | 
					                            expression: expression.span(),
 | 
				
			||||||
                            expected_type: to.value_type().into(),
 | 
					                            expected_type: to.value_type().into(),
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                        handler.receive(Box::new(err.clone()));
 | 
					                        handler.receive(err.clone());
 | 
				
			||||||
                        Err(err)
 | 
					                        Err(err)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -1221,7 +1228,7 @@ impl Transpiler {
 | 
				
			||||||
                        expected_type: ExpectedType::Boolean,
 | 
					                        expected_type: ExpectedType::Boolean,
 | 
				
			||||||
                        expression: expression.span(),
 | 
					                        expression: expression.span(),
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    handler.receive(Box::new(err.clone()));
 | 
					                    handler.receive(err.clone());
 | 
				
			||||||
                    Err(err)
 | 
					                    Err(err)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -1230,7 +1237,7 @@ impl Transpiler {
 | 
				
			||||||
                    expected_type: to.value_type().into(),
 | 
					                    expected_type: to.value_type().into(),
 | 
				
			||||||
                    expression: expression.span(),
 | 
					                    expression: expression.span(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                handler.receive(Box::new(err.clone()));
 | 
					                handler.receive(err.clone());
 | 
				
			||||||
                Err(err)
 | 
					                Err(err)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ use std::borrow::Cow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Escapes `"` and `\` in a string.
 | 
					/// Escapes `"` and `\` in a string.
 | 
				
			||||||
#[must_use]
 | 
					#[must_use]
 | 
				
			||||||
pub fn escape_str(s: &str) -> Cow<'_, str> {
 | 
					pub fn escape_str(s: &str) -> Cow<str> {
 | 
				
			||||||
    if s.contains('"') || s.contains('\\') {
 | 
					    if s.contains('"') || s.contains('\\') {
 | 
				
			||||||
        let mut escaped = String::with_capacity(s.len());
 | 
					        let mut escaped = String::with_capacity(s.len());
 | 
				
			||||||
        for c in s.chars() {
 | 
					        for c in s.chars() {
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ pub fn escape_str(s: &str) -> Cow<'_, str> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Unescapes '\`', `\`, `\n`, `\r` and `\t` in a string.
 | 
					/// Unescapes '\`', `\`, `\n`, `\r` and `\t` in a string.
 | 
				
			||||||
#[must_use]
 | 
					#[must_use]
 | 
				
			||||||
pub fn unescape_macro_string(s: &str) -> Cow<'_, str> {
 | 
					pub fn unescape_macro_string(s: &str) -> Cow<str> {
 | 
				
			||||||
    if s.contains('\\') || s.contains('`') {
 | 
					    if s.contains('\\') || s.contains('`') {
 | 
				
			||||||
        Cow::Owned(
 | 
					        Cow::Owned(
 | 
				
			||||||
            s.replace("\\n", "\n")
 | 
					            s.replace("\\n", "\n")
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ pub fn unescape_macro_string(s: &str) -> Cow<'_, str> {
 | 
				
			||||||
/// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`.
 | 
					/// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`.
 | 
				
			||||||
#[cfg(feature = "shulkerbox")]
 | 
					#[cfg(feature = "shulkerbox")]
 | 
				
			||||||
#[must_use]
 | 
					#[must_use]
 | 
				
			||||||
pub fn identifier_to_macro(ident: &str) -> std::borrow::Cow<'_, str> {
 | 
					pub fn identifier_to_macro(ident: &str) -> std::borrow::Cow<str> {
 | 
				
			||||||
    if ident.contains("__")
 | 
					    if ident.contains("__")
 | 
				
			||||||
        || ident
 | 
					        || ident
 | 
				
			||||||
            .chars()
 | 
					            .chars()
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ pub fn identifier_to_macro(ident: &str) -> std::borrow::Cow<str> {
 | 
				
			||||||
/// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`.
 | 
					/// Transforms an identifier to a macro name that only contains `a-zA-Z0-9_`.
 | 
				
			||||||
#[cfg(feature = "shulkerbox")]
 | 
					#[cfg(feature = "shulkerbox")]
 | 
				
			||||||
#[must_use]
 | 
					#[must_use]
 | 
				
			||||||
pub fn identifier_to_scoreboard_target(ident: &str) -> std::borrow::Cow<'_, str> {
 | 
					pub fn identifier_to_scoreboard_target(ident: &str) -> std::borrow::Cow<str> {
 | 
				
			||||||
    if !(..=16).contains(&ident.len())
 | 
					    if !(..=16).contains(&ident.len())
 | 
				
			||||||
        || ident
 | 
					        || ident
 | 
				
			||||||
            .chars()
 | 
					            .chars()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,10 @@ fn parsing_test1() {
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .expect("Failed to parse");
 | 
					    .expect("Failed to parse");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert_eq!(parsed.namespace().name().str_content(), "parsing-test");
 | 
					    assert_eq!(
 | 
				
			||||||
 | 
					        parsed.namespace().namespace_name().str_content(),
 | 
				
			||||||
 | 
					        "parsing-test"
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let declarations = parsed.declarations();
 | 
					    let declarations = parsed.declarations();
 | 
				
			||||||
    assert_eq!(declarations.len(), 1);
 | 
					    assert_eq!(declarations.len(), 1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue