add handling for template strings everywhere
This commit is contained in:
		
							parent
							
								
									6043a4add5
								
							
						
					
					
						commit
						1b85a2f654
					
				| 
						 | 
					@ -30,12 +30,12 @@ derive_more = { version = "2.0.1", default-features = false, features = [ "deref
 | 
				
			||||||
enum-as-inner = "0.6.0"
 | 
					enum-as-inner = "0.6.0"
 | 
				
			||||||
getset = "0.1.2"
 | 
					getset = "0.1.2"
 | 
				
			||||||
itertools = "0.14.0"
 | 
					itertools = "0.14.0"
 | 
				
			||||||
mlua = { version = "0.10.2", features = ["lua54", "vendored"], optional = true }
 | 
					mlua = { version = "0.11.3", features = ["lua54", "vendored"], optional = true }
 | 
				
			||||||
pathdiff = "0.2.3"
 | 
					pathdiff = "0.2.3"
 | 
				
			||||||
serde = { version = "1.0.217", features = ["derive"], optional = true }
 | 
					serde = { version = "1.0.217", features = ["derive"], optional = true }
 | 
				
			||||||
serde_json = { version = "1.0.138", optional = true }
 | 
					serde_json = { version = "1.0.138", optional = true }
 | 
				
			||||||
# shulkerbox = { version = "0.1.0", default-features = false, optional = true }
 | 
					# shulkerbox = { version = "0.1.0", default-features = false, optional = true }
 | 
				
			||||||
shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox", rev = "89709834da6f39840caa9c6a2eadbdececdc7d44", default-features = false, optional = true }
 | 
					shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox", rev = "d4689c696a35328c041bcbbfd203abd5818c46d3", default-features = false, optional = true }
 | 
				
			||||||
strsim = "0.11.1"
 | 
					strsim = "0.11.1"
 | 
				
			||||||
strum = { version = "0.27.0", features = ["derive"] }
 | 
					strum = { version = "0.27.0", features = ["derive"] }
 | 
				
			||||||
thiserror = "2.0.11"
 | 
					thiserror = "2.0.11"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -984,8 +984,11 @@ impl Parser<'_> {
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> ParseResult<AnyStringLiteral> {
 | 
					    ) -> ParseResult<AnyStringLiteral> {
 | 
				
			||||||
        match self.next_significant_token() {
 | 
					        match self.stop_at_significant() {
 | 
				
			||||||
            Reading::Atomic(Token::StringLiteral(literal)) => Ok(literal.into()),
 | 
					            Reading::Atomic(Token::StringLiteral(literal)) => {
 | 
				
			||||||
 | 
					                self.forward();
 | 
				
			||||||
 | 
					                Ok(literal.into())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '`' => self
 | 
					            Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '`' => self
 | 
				
			||||||
                .parse_template_string_literal(handler)
 | 
					                .parse_template_string_literal(handler)
 | 
				
			||||||
                .map(AnyStringLiteral::TemplateStringLiteral),
 | 
					                .map(AnyStringLiteral::TemplateStringLiteral),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -812,7 +812,7 @@ impl Parser<'_> {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Reading::Atomic(Token::Keyword(keyword)) if keyword.keyword.starts_execute_block() => {
 | 
					            Reading::Atomic(Token::Keyword(keyword)) if keyword.keyword.starts_execute_block() => {
 | 
				
			||||||
                // eat the as keyword
 | 
					                // eat the keyword
 | 
				
			||||||
                self.forward();
 | 
					                self.forward();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let argument = match self.stop_at_significant() {
 | 
					                let argument = match self.stop_at_significant() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ use crate::{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::util::{MacroString, MacroStringPart};
 | 
					use super::util::{MacroString, MacroStringPart};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ShulkerboxMacroStringMap = BTreeMap<String, (DataLocation, Vec<Command>, Span)>;
 | 
					pub(crate) type ShulkerboxMacroStringMap = BTreeMap<String, (DataLocation, Vec<Command>, Span)>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl MacroString {
 | 
					impl MacroString {
 | 
				
			||||||
    pub fn into_sb(self) -> (ExtMacroString, ShulkerboxMacroStringMap) {
 | 
					    pub fn into_sb(self) -> (ExtMacroString, ShulkerboxMacroStringMap) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::fmt::Display;
 | 
					use std::fmt::Display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(feature = "shulkerbox")]
 | 
				
			||||||
 | 
					use std::collections::BTreeMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(feature = "shulkerbox")]
 | 
					#[cfg(feature = "shulkerbox")]
 | 
				
			||||||
use enum_as_inner::EnumAsInner;
 | 
					use enum_as_inner::EnumAsInner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +28,7 @@ use crate::{
 | 
				
			||||||
        Primary,
 | 
					        Primary,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    transpile::{
 | 
					    transpile::{
 | 
				
			||||||
 | 
					        conversions::ShulkerboxMacroStringMap,
 | 
				
			||||||
        error::{FunctionArgumentsNotAllowed, MissingValue},
 | 
					        error::{FunctionArgumentsNotAllowed, MissingValue},
 | 
				
			||||||
        variables::FunctionVariableDataType,
 | 
					        variables::FunctionVariableDataType,
 | 
				
			||||||
        TranspileError,
 | 
					        TranspileError,
 | 
				
			||||||
| 
						 | 
					@ -217,10 +221,9 @@ impl StorageType {
 | 
				
			||||||
    pub fn suffix(&self) -> &'static str {
 | 
					    pub fn suffix(&self) -> &'static str {
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            Self::Boolean | Self::Byte => "b",
 | 
					            Self::Boolean | Self::Byte => "b",
 | 
				
			||||||
            Self::Int => "",
 | 
					            Self::Int | Self::String => "",
 | 
				
			||||||
            Self::Long => "l",
 | 
					            Self::Long => "l",
 | 
				
			||||||
            Self::Double => "d",
 | 
					            Self::Double => "d",
 | 
				
			||||||
            Self::String => "",
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1291,14 +1294,14 @@ impl Transpiler {
 | 
				
			||||||
                        ..
 | 
					                        ..
 | 
				
			||||||
                    } | DataLocation::Tag { .. }
 | 
					                    } | DataLocation::Tag { .. }
 | 
				
			||||||
                ) {
 | 
					                ) {
 | 
				
			||||||
                    let (mut cmds, cond) =
 | 
					                    let (mut cmds, prepare_variables, cond) =
 | 
				
			||||||
                        self.transpile_primary_expression_as_condition(primary, scope, handler)?;
 | 
					                        self.transpile_primary_expression_as_condition(primary, scope, handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let store_cmds =
 | 
					                    let store_cmds =
 | 
				
			||||||
                        self.store_condition_success(cond, target, primary, handler)?;
 | 
					                        self.store_condition_success(cond, target, primary, handler)?;
 | 
				
			||||||
                    cmds.extend(store_cmds);
 | 
					                    cmds.extend(store_cmds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Ok(cmds)
 | 
					                    self.transpile_commands_with_variable_macros(cmds, prepare_variables, handler)
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
					                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
				
			||||||
                        expected_type: target.value_type().into(),
 | 
					                        expected_type: target.value_type().into(),
 | 
				
			||||||
| 
						 | 
					@ -1375,14 +1378,14 @@ impl Transpiler {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                PrefixOperator::LogicalNot(_) => {
 | 
					                PrefixOperator::LogicalNot(_) => {
 | 
				
			||||||
                    let (mut cmds, cond) =
 | 
					                    let (mut cmds, prepare_variables, cond) =
 | 
				
			||||||
                        self.transpile_primary_expression_as_condition(primary, scope, handler)?;
 | 
					                        self.transpile_primary_expression_as_condition(primary, scope, handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let store_cmds =
 | 
					                    let store_cmds =
 | 
				
			||||||
                        self.store_condition_success(cond, target, primary, handler)?;
 | 
					                        self.store_condition_success(cond, target, primary, handler)?;
 | 
				
			||||||
                    cmds.extend(store_cmds);
 | 
					                    cmds.extend(store_cmds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Ok(cmds)
 | 
					                    self.transpile_commands_with_variable_macros(cmds, prepare_variables, handler)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                PrefixOperator::Run(_) => {
 | 
					                PrefixOperator::Run(_) => {
 | 
				
			||||||
                    let run_cmds =
 | 
					                    let run_cmds =
 | 
				
			||||||
| 
						 | 
					@ -1646,13 +1649,13 @@ impl Transpiler {
 | 
				
			||||||
                | BinaryOperator::NotEqual(..)
 | 
					                | BinaryOperator::NotEqual(..)
 | 
				
			||||||
                | BinaryOperator::LogicalAnd(..)
 | 
					                | BinaryOperator::LogicalAnd(..)
 | 
				
			||||||
                | BinaryOperator::LogicalOr(..) => {
 | 
					                | BinaryOperator::LogicalOr(..) => {
 | 
				
			||||||
                    let (mut cmds, cond) =
 | 
					                    let (mut cmds, prepare_variables, cond) =
 | 
				
			||||||
                        self.transpile_binary_expression_as_condition(binary, scope, handler)?;
 | 
					                        self.transpile_binary_expression_as_condition(binary, scope, handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let store_cmds = self.store_condition_success(cond, target, binary, handler)?;
 | 
					                    let store_cmds = self.store_condition_success(cond, target, binary, handler)?;
 | 
				
			||||||
                    cmds.extend(store_cmds);
 | 
					                    cmds.extend(store_cmds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Ok(cmds)
 | 
					                    self.transpile_commands_with_variable_macros(cmds, prepare_variables, handler)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1663,7 +1666,7 @@ impl Transpiler {
 | 
				
			||||||
        expression: &Expression,
 | 
					        expression: &Expression,
 | 
				
			||||||
        scope: &Arc<super::Scope>,
 | 
					        scope: &Arc<super::Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<(Vec<Command>, ExtendedCondition)> {
 | 
					    ) -> TranspileResult<(Vec<Command>, ShulkerboxMacroStringMap, ExtendedCondition)> {
 | 
				
			||||||
        match expression {
 | 
					        match expression {
 | 
				
			||||||
            Expression::Primary(primary) => {
 | 
					            Expression::Primary(primary) => {
 | 
				
			||||||
                self.transpile_primary_expression_as_condition(primary, scope, handler)
 | 
					                self.transpile_primary_expression_as_condition(primary, scope, handler)
 | 
				
			||||||
| 
						 | 
					@ -1680,11 +1683,15 @@ impl Transpiler {
 | 
				
			||||||
        primary: &Primary,
 | 
					        primary: &Primary,
 | 
				
			||||||
        scope: &Arc<super::Scope>,
 | 
					        scope: &Arc<super::Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<(Vec<Command>, ExtendedCondition)> {
 | 
					    ) -> TranspileResult<(Vec<Command>, ShulkerboxMacroStringMap, ExtendedCondition)> {
 | 
				
			||||||
 | 
					        use std::collections::BTreeMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match primary {
 | 
					        match primary {
 | 
				
			||||||
            Primary::Boolean(boolean) => {
 | 
					            Primary::Boolean(boolean) => Ok((
 | 
				
			||||||
                Ok((Vec::new(), ExtendedCondition::Comptime(boolean.value())))
 | 
					                Vec::new(),
 | 
				
			||||||
            }
 | 
					                BTreeMap::new(),
 | 
				
			||||||
 | 
					                ExtendedCondition::Comptime(boolean.value()),
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
            Primary::Integer(_) => {
 | 
					            Primary::Integer(_) => {
 | 
				
			||||||
                let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
					                let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
				
			||||||
                    expected_type: ExpectedType::Boolean,
 | 
					                    expected_type: ExpectedType::Boolean,
 | 
				
			||||||
| 
						 | 
					@ -1695,6 +1702,7 @@ impl Transpiler {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Primary::StringLiteral(s) => Ok((
 | 
					            Primary::StringLiteral(s) => Ok((
 | 
				
			||||||
                Vec::new(),
 | 
					                Vec::new(),
 | 
				
			||||||
 | 
					                BTreeMap::new(),
 | 
				
			||||||
                ExtendedCondition::Runtime(Condition::Atom(s.str_content().to_string().into())),
 | 
					                ExtendedCondition::Runtime(Condition::Atom(s.str_content().to_string().into())),
 | 
				
			||||||
            )),
 | 
					            )),
 | 
				
			||||||
            Primary::TemplateStringLiteral(template_string) => {
 | 
					            Primary::TemplateStringLiteral(template_string) => {
 | 
				
			||||||
| 
						 | 
					@ -1703,6 +1711,7 @@ impl Transpiler {
 | 
				
			||||||
                    .into_sb();
 | 
					                    .into_sb();
 | 
				
			||||||
                Ok((
 | 
					                Ok((
 | 
				
			||||||
                    Vec::new(),
 | 
					                    Vec::new(),
 | 
				
			||||||
 | 
					                    prepare_variables,
 | 
				
			||||||
                    ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
					                    ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
				
			||||||
                ))
 | 
					                ))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1730,6 +1739,7 @@ impl Transpiler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Ok((
 | 
					                    Ok((
 | 
				
			||||||
                        Vec::new(),
 | 
					                        Vec::new(),
 | 
				
			||||||
 | 
					                        BTreeMap::new(),
 | 
				
			||||||
                        ExtendedCondition::Runtime(Condition::Atom(
 | 
					                        ExtendedCondition::Runtime(Condition::Atom(
 | 
				
			||||||
                            format!("function {func_location}").into(),
 | 
					                            format!("function {func_location}").into(),
 | 
				
			||||||
                        )),
 | 
					                        )),
 | 
				
			||||||
| 
						 | 
					@ -1742,12 +1752,14 @@ impl Transpiler {
 | 
				
			||||||
                    match variable {
 | 
					                    match variable {
 | 
				
			||||||
                        VariableData::BooleanStorage { storage_name, path } => Ok((
 | 
					                        VariableData::BooleanStorage { storage_name, path } => Ok((
 | 
				
			||||||
                            Vec::new(),
 | 
					                            Vec::new(),
 | 
				
			||||||
 | 
					                            BTreeMap::new(),
 | 
				
			||||||
                            ExtendedCondition::Runtime(Condition::Atom(
 | 
					                            ExtendedCondition::Runtime(Condition::Atom(
 | 
				
			||||||
                                format!("data storage {storage_name} {{{path}: 1b}}").into(),
 | 
					                                format!("data storage {storage_name} {{{path}: 1b}}").into(),
 | 
				
			||||||
                            )),
 | 
					                            )),
 | 
				
			||||||
                        )),
 | 
					                        )),
 | 
				
			||||||
                        VariableData::MacroParameter { macro_name, .. } => Ok((
 | 
					                        VariableData::MacroParameter { macro_name, .. } => Ok((
 | 
				
			||||||
                            Vec::new(),
 | 
					                            Vec::new(),
 | 
				
			||||||
 | 
					                            BTreeMap::new(),
 | 
				
			||||||
                            ExtendedCondition::Runtime(Condition::Atom(
 | 
					                            ExtendedCondition::Runtime(Condition::Atom(
 | 
				
			||||||
                                shulkerbox::util::MacroString::MacroString(vec![
 | 
					                                shulkerbox::util::MacroString::MacroString(vec![
 | 
				
			||||||
                                    shulkerbox::util::MacroStringPart::MacroUsage(
 | 
					                                    shulkerbox::util::MacroStringPart::MacroUsage(
 | 
				
			||||||
| 
						 | 
					@ -1806,6 +1818,7 @@ impl Transpiler {
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    Ok((
 | 
					                                    Ok((
 | 
				
			||||||
                                        Vec::new(),
 | 
					                                        Vec::new(),
 | 
				
			||||||
 | 
					                                        BTreeMap::new(),
 | 
				
			||||||
                                        ExtendedCondition::Runtime(Condition::Atom(
 | 
					                                        ExtendedCondition::Runtime(Condition::Atom(
 | 
				
			||||||
                                            format!("data storage {storage_name} {{{path}: 1b}}")
 | 
					                                            format!("data storage {storage_name} {{{path}: 1b}}")
 | 
				
			||||||
                                                .into(),
 | 
					                                                .into(),
 | 
				
			||||||
| 
						 | 
					@ -1869,7 +1882,7 @@ impl Transpiler {
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    |value| match value {
 | 
					                    |value| match value {
 | 
				
			||||||
                        ComptimeValue::Boolean(b) => {
 | 
					                        ComptimeValue::Boolean(b) => {
 | 
				
			||||||
                            Ok((Vec::new(), ExtendedCondition::Comptime(b)))
 | 
					                            Ok((Vec::new(), BTreeMap::new(), ExtendedCondition::Comptime(b)))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        ComptimeValue::Integer(_) => {
 | 
					                        ComptimeValue::Integer(_) => {
 | 
				
			||||||
                            let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
					                            let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
				
			||||||
| 
						 | 
					@ -1881,6 +1894,7 @@ impl Transpiler {
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        ComptimeValue::String(s) => Ok((
 | 
					                        ComptimeValue::String(s) => Ok((
 | 
				
			||||||
                            Vec::new(),
 | 
					                            Vec::new(),
 | 
				
			||||||
 | 
					                            BTreeMap::new(),
 | 
				
			||||||
                            ExtendedCondition::Runtime(Condition::Atom(
 | 
					                            ExtendedCondition::Runtime(Condition::Atom(
 | 
				
			||||||
                                shulkerbox::util::MacroString::String(s),
 | 
					                                shulkerbox::util::MacroString::String(s),
 | 
				
			||||||
                            )),
 | 
					                            )),
 | 
				
			||||||
| 
						 | 
					@ -1889,6 +1903,7 @@ impl Transpiler {
 | 
				
			||||||
                            let (macro_string, prepare_variables) = s.into_sb();
 | 
					                            let (macro_string, prepare_variables) = s.into_sb();
 | 
				
			||||||
                            Ok((
 | 
					                            Ok((
 | 
				
			||||||
                                Vec::new(),
 | 
					                                Vec::new(),
 | 
				
			||||||
 | 
					                                prepare_variables,
 | 
				
			||||||
                                ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
					                                ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
				
			||||||
                            ))
 | 
					                            ))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -1896,13 +1911,15 @@ impl Transpiler {
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
            Primary::Prefix(prefix) => match prefix.operator() {
 | 
					            Primary::Prefix(prefix) => match prefix.operator() {
 | 
				
			||||||
                PrefixOperator::LogicalNot(_) => {
 | 
					                PrefixOperator::LogicalNot(_) => {
 | 
				
			||||||
                    let (cmds, cond) = self.transpile_primary_expression_as_condition(
 | 
					                    let (cmds, prepare_variables, cond) = self
 | 
				
			||||||
                        prefix.operand(),
 | 
					                        .transpile_primary_expression_as_condition(
 | 
				
			||||||
                        scope,
 | 
					                            prefix.operand(),
 | 
				
			||||||
                        handler,
 | 
					                            scope,
 | 
				
			||||||
                    )?;
 | 
					                            handler,
 | 
				
			||||||
 | 
					                        )?;
 | 
				
			||||||
                    Ok((
 | 
					                    Ok((
 | 
				
			||||||
                        cmds,
 | 
					                        cmds,
 | 
				
			||||||
 | 
					                        prepare_variables,
 | 
				
			||||||
                        match cond {
 | 
					                        match cond {
 | 
				
			||||||
                            ExtendedCondition::Runtime(cond) => {
 | 
					                            ExtendedCondition::Runtime(cond) => {
 | 
				
			||||||
                                ExtendedCondition::Runtime(Condition::Not(Box::new(cond)))
 | 
					                                ExtendedCondition::Runtime(Condition::Not(Box::new(cond)))
 | 
				
			||||||
| 
						 | 
					@ -1928,7 +1945,7 @@ impl Transpiler {
 | 
				
			||||||
                        scope,
 | 
					                        scope,
 | 
				
			||||||
                        handler,
 | 
					                        handler,
 | 
				
			||||||
                    )?;
 | 
					                    )?;
 | 
				
			||||||
                    Ok((store_cmds, cond))
 | 
					                    Ok((store_cmds, BTreeMap::new(), cond))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                PrefixOperator::Negate(_) => {
 | 
					                PrefixOperator::Negate(_) => {
 | 
				
			||||||
                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
					                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
				
			||||||
| 
						 | 
					@ -1942,18 +1959,22 @@ impl Transpiler {
 | 
				
			||||||
            Primary::Lua(lua) => match lua.eval_comptime(scope, handler)? {
 | 
					            Primary::Lua(lua) => match lua.eval_comptime(scope, handler)? {
 | 
				
			||||||
                Ok(ComptimeValue::String(value)) => Ok((
 | 
					                Ok(ComptimeValue::String(value)) => Ok((
 | 
				
			||||||
                    Vec::new(),
 | 
					                    Vec::new(),
 | 
				
			||||||
 | 
					                    BTreeMap::new(),
 | 
				
			||||||
                    ExtendedCondition::Runtime(Condition::Atom(value.into())),
 | 
					                    ExtendedCondition::Runtime(Condition::Atom(value.into())),
 | 
				
			||||||
                )),
 | 
					                )),
 | 
				
			||||||
                Ok(ComptimeValue::MacroString(value)) => {
 | 
					                Ok(ComptimeValue::MacroString(value)) => {
 | 
				
			||||||
                    let (macro_string, prepare_variables) = value.into_sb();
 | 
					                    let (macro_string, prepare_variables) = value.into_sb();
 | 
				
			||||||
                    Ok((
 | 
					                    Ok((
 | 
				
			||||||
                        Vec::new(),
 | 
					                        Vec::new(),
 | 
				
			||||||
 | 
					                        prepare_variables,
 | 
				
			||||||
                        ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
					                        ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
				
			||||||
                    ))
 | 
					                    ))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Ok(ComptimeValue::Boolean(boolean)) => {
 | 
					                Ok(ComptimeValue::Boolean(boolean)) => Ok((
 | 
				
			||||||
                    Ok((Vec::new(), ExtendedCondition::Comptime(boolean)))
 | 
					                    Vec::new(),
 | 
				
			||||||
                }
 | 
					                    BTreeMap::new(),
 | 
				
			||||||
 | 
					                    ExtendedCondition::Comptime(boolean),
 | 
				
			||||||
 | 
					                )),
 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
					                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
				
			||||||
                        expected_type: ExpectedType::Boolean,
 | 
					                        expected_type: ExpectedType::Boolean,
 | 
				
			||||||
| 
						 | 
					@ -1971,7 +1992,7 @@ impl Transpiler {
 | 
				
			||||||
        binary: &Binary,
 | 
					        binary: &Binary,
 | 
				
			||||||
        scope: &Arc<super::Scope>,
 | 
					        scope: &Arc<super::Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<(Vec<Command>, ExtendedCondition)> {
 | 
					    ) -> TranspileResult<(Vec<Command>, ShulkerboxMacroStringMap, ExtendedCondition)> {
 | 
				
			||||||
        match binary.operator() {
 | 
					        match binary.operator() {
 | 
				
			||||||
            BinaryOperator::Equal(..)
 | 
					            BinaryOperator::Equal(..)
 | 
				
			||||||
            | BinaryOperator::NotEqual(..)
 | 
					            | BinaryOperator::NotEqual(..)
 | 
				
			||||||
| 
						 | 
					@ -1980,7 +2001,9 @@ impl Transpiler {
 | 
				
			||||||
            | BinaryOperator::LessThan(_)
 | 
					            | BinaryOperator::LessThan(_)
 | 
				
			||||||
            | BinaryOperator::LessThanOrEqual(..) => self
 | 
					            | BinaryOperator::LessThanOrEqual(..) => self
 | 
				
			||||||
                .transpile_comparison_operator(binary, scope, handler)
 | 
					                .transpile_comparison_operator(binary, scope, handler)
 | 
				
			||||||
                .map(|(cmds, cond)| (cmds, ExtendedCondition::Runtime(cond))),
 | 
					                .map(|(cmds, prepare_variables, cond)| {
 | 
				
			||||||
 | 
					                    (cmds, prepare_variables, ExtendedCondition::Runtime(cond))
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
            BinaryOperator::LogicalAnd(..) | BinaryOperator::LogicalOr(..) => {
 | 
					            BinaryOperator::LogicalAnd(..) | BinaryOperator::LogicalOr(..) => {
 | 
				
			||||||
                self.transpile_logic_operator(binary, scope, handler)
 | 
					                self.transpile_logic_operator(binary, scope, handler)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -2132,7 +2155,7 @@ impl Transpiler {
 | 
				
			||||||
        binary: &Binary,
 | 
					        binary: &Binary,
 | 
				
			||||||
        scope: &Arc<super::Scope>,
 | 
					        scope: &Arc<super::Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<(Vec<Command>, Condition)> {
 | 
					    ) -> TranspileResult<(Vec<Command>, ShulkerboxMacroStringMap, Condition)> {
 | 
				
			||||||
        let invert = matches!(binary.operator(), BinaryOperator::NotEqual(..));
 | 
					        let invert = matches!(binary.operator(), BinaryOperator::NotEqual(..));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO: evaluate comptime values and compare using `matches` and integer ranges
 | 
					        // TODO: evaluate comptime values and compare using `matches` and integer ranges
 | 
				
			||||||
| 
						 | 
					@ -2177,6 +2200,7 @@ impl Transpiler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok((
 | 
					        Ok((
 | 
				
			||||||
            left_cmds.into_iter().chain(right_cmds).collect(),
 | 
					            left_cmds.into_iter().chain(right_cmds).collect(),
 | 
				
			||||||
 | 
					            BTreeMap::new(),
 | 
				
			||||||
            if invert {
 | 
					            if invert {
 | 
				
			||||||
                Condition::Not(Box::new(condition))
 | 
					                Condition::Not(Box::new(condition))
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
| 
						 | 
					@ -2190,38 +2214,45 @@ impl Transpiler {
 | 
				
			||||||
        binary: &Binary,
 | 
					        binary: &Binary,
 | 
				
			||||||
        scope: &Arc<super::Scope>,
 | 
					        scope: &Arc<super::Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<(Vec<Command>, ExtendedCondition)> {
 | 
					    ) -> TranspileResult<(Vec<Command>, ShulkerboxMacroStringMap, ExtendedCondition)> {
 | 
				
			||||||
        let left = binary.left_operand().as_ref();
 | 
					        let left = binary.left_operand().as_ref();
 | 
				
			||||||
        let right = binary.right_operand().as_ref();
 | 
					        let right = binary.right_operand().as_ref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (left_cmds, left_cond) =
 | 
					        let (left_cmds, mut left_prep_variables, left_cond) =
 | 
				
			||||||
            self.transpile_expression_as_condition(left, scope, handler)?;
 | 
					            self.transpile_expression_as_condition(left, scope, handler)?;
 | 
				
			||||||
        let (right_cmds, right_cond) =
 | 
					        let (right_cmds, right_prep_variables, right_cond) =
 | 
				
			||||||
            self.transpile_expression_as_condition(right, scope, handler)?;
 | 
					            self.transpile_expression_as_condition(right, scope, handler)?;
 | 
				
			||||||
 | 
					        left_prep_variables.extend(right_prep_variables);
 | 
				
			||||||
 | 
					        let prep_variables = left_prep_variables;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match (binary.operator(), left_cond, right_cond) {
 | 
					        match (binary.operator(), left_cond, right_cond) {
 | 
				
			||||||
            (BinaryOperator::LogicalAnd(..), ExtendedCondition::Comptime(true), other)
 | 
					            (BinaryOperator::LogicalAnd(..), ExtendedCondition::Comptime(true), other)
 | 
				
			||||||
            | (BinaryOperator::LogicalOr(..), ExtendedCondition::Comptime(false), other) => {
 | 
					            | (BinaryOperator::LogicalOr(..), ExtendedCondition::Comptime(false), other) => {
 | 
				
			||||||
                Ok((right_cmds, other))
 | 
					                Ok((right_cmds, prep_variables, other))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            (BinaryOperator::LogicalAnd(..), other, ExtendedCondition::Comptime(true))
 | 
					            (BinaryOperator::LogicalAnd(..), other, ExtendedCondition::Comptime(true))
 | 
				
			||||||
            | (BinaryOperator::LogicalOr(..), other, ExtendedCondition::Comptime(false)) => {
 | 
					            | (BinaryOperator::LogicalOr(..), other, ExtendedCondition::Comptime(false)) => {
 | 
				
			||||||
                Ok((left_cmds, other))
 | 
					                Ok((left_cmds, prep_variables, other))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            (BinaryOperator::LogicalAnd(..), ExtendedCondition::Comptime(false), _)
 | 
					            (BinaryOperator::LogicalAnd(..), ExtendedCondition::Comptime(false), _)
 | 
				
			||||||
            | (BinaryOperator::LogicalAnd(..), _, ExtendedCondition::Comptime(false)) => {
 | 
					            | (BinaryOperator::LogicalAnd(..), _, ExtendedCondition::Comptime(false)) => Ok((
 | 
				
			||||||
                Ok((Vec::new(), ExtendedCondition::Comptime(false)))
 | 
					                Vec::new(),
 | 
				
			||||||
            }
 | 
					                BTreeMap::new(),
 | 
				
			||||||
 | 
					                ExtendedCondition::Comptime(false),
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
            (BinaryOperator::LogicalOr(..), ExtendedCondition::Comptime(true), _)
 | 
					            (BinaryOperator::LogicalOr(..), ExtendedCondition::Comptime(true), _)
 | 
				
			||||||
            | (BinaryOperator::LogicalOr(..), _, ExtendedCondition::Comptime(true)) => {
 | 
					            | (BinaryOperator::LogicalOr(..), _, ExtendedCondition::Comptime(true)) => Ok((
 | 
				
			||||||
                Ok((Vec::new(), ExtendedCondition::Comptime(true)))
 | 
					                Vec::new(),
 | 
				
			||||||
            }
 | 
					                BTreeMap::new(),
 | 
				
			||||||
 | 
					                ExtendedCondition::Comptime(true),
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
                BinaryOperator::LogicalAnd(..),
 | 
					                BinaryOperator::LogicalAnd(..),
 | 
				
			||||||
                ExtendedCondition::Runtime(left_cond),
 | 
					                ExtendedCondition::Runtime(left_cond),
 | 
				
			||||||
                ExtendedCondition::Runtime(right_cond),
 | 
					                ExtendedCondition::Runtime(right_cond),
 | 
				
			||||||
            ) => Ok((
 | 
					            ) => Ok((
 | 
				
			||||||
                left_cmds.into_iter().chain(right_cmds).collect(),
 | 
					                left_cmds.into_iter().chain(right_cmds).collect(),
 | 
				
			||||||
 | 
					                prep_variables,
 | 
				
			||||||
                ExtendedCondition::Runtime(Condition::And(
 | 
					                ExtendedCondition::Runtime(Condition::And(
 | 
				
			||||||
                    Box::new(left_cond),
 | 
					                    Box::new(left_cond),
 | 
				
			||||||
                    Box::new(right_cond),
 | 
					                    Box::new(right_cond),
 | 
				
			||||||
| 
						 | 
					@ -2233,6 +2264,7 @@ impl Transpiler {
 | 
				
			||||||
                ExtendedCondition::Runtime(right_cond),
 | 
					                ExtendedCondition::Runtime(right_cond),
 | 
				
			||||||
            ) => Ok((
 | 
					            ) => Ok((
 | 
				
			||||||
                left_cmds.into_iter().chain(right_cmds).collect(),
 | 
					                left_cmds.into_iter().chain(right_cmds).collect(),
 | 
				
			||||||
 | 
					                prep_variables,
 | 
				
			||||||
                ExtendedCondition::Runtime(Condition::Or(
 | 
					                ExtendedCondition::Runtime(Condition::Or(
 | 
				
			||||||
                    Box::new(left_cond),
 | 
					                    Box::new(left_cond),
 | 
				
			||||||
                    Box::new(right_cond),
 | 
					                    Box::new(right_cond),
 | 
				
			||||||
| 
						 | 
					@ -2335,11 +2367,17 @@ impl Transpiler {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    | DataLocation::Tag { .. } => {
 | 
					                    | DataLocation::Tag { .. } => {
 | 
				
			||||||
                        let (macro_string, prepare_variables) = value.clone().into_sb();
 | 
					                        let (macro_string, prepare_variables) = value.clone().into_sb();
 | 
				
			||||||
                        self.store_condition_success(
 | 
					                        let cmds = self.store_condition_success(
 | 
				
			||||||
                            ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
					                            ExtendedCondition::Runtime(Condition::Atom(macro_string)),
 | 
				
			||||||
                            target,
 | 
					                            target,
 | 
				
			||||||
                            source,
 | 
					                            source,
 | 
				
			||||||
                            handler,
 | 
					                            handler,
 | 
				
			||||||
 | 
					                        )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        self.transpile_commands_with_variable_macros(
 | 
				
			||||||
 | 
					                            cmds,
 | 
				
			||||||
 | 
					                            prepare_variables,
 | 
				
			||||||
 | 
					                            handler,
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    // DataLocation::Storage { storage_name, path, r#type: StorageType::String } => todo!("implement storage string")
 | 
					                    // DataLocation::Storage { storage_name, path, r#type: StorageType::String } => todo!("implement storage string")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -682,8 +682,8 @@ impl Transpiler {
 | 
				
			||||||
                                                return Err(err);
 | 
					                                                return Err(err);
 | 
				
			||||||
                                            }
 | 
					                                            }
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                        Err((parts, preparation_variables)) => {
 | 
					                                        Err((parts, prepare_variables)) => {
 | 
				
			||||||
                                            let (macro_string, preparation_variables) = MacroString::MacroString {
 | 
					                                            let (macro_string, prepare_variables) = MacroString::MacroString {
 | 
				
			||||||
                                                parts: std::iter::once(MacroStringPart::String(
 | 
					                                                parts: std::iter::once(MacroStringPart::String(
 | 
				
			||||||
                                                    format!(
 | 
					                                                    format!(
 | 
				
			||||||
                                                        "scoreboard players set {target} {objective} "
 | 
					                                                        "scoreboard players set {target} {objective} "
 | 
				
			||||||
| 
						 | 
					@ -691,10 +691,16 @@ impl Transpiler {
 | 
				
			||||||
                                                ))
 | 
					                                                ))
 | 
				
			||||||
                                                .chain(parts.iter().cloned())
 | 
					                                                .chain(parts.iter().cloned())
 | 
				
			||||||
                                                .collect(),
 | 
					                                                .collect(),
 | 
				
			||||||
                                                prepare_variables: preparation_variables.to_owned(),
 | 
					                                                prepare_variables: prepare_variables.to_owned(),
 | 
				
			||||||
                                            }
 | 
					                                            }
 | 
				
			||||||
                                            .into_sb();
 | 
					                                            .into_sb();
 | 
				
			||||||
                                            move_cmds.push(Command::UsesMacro(macro_string));
 | 
					                                            let cmds = self
 | 
				
			||||||
 | 
					                                                .transpile_commands_with_variable_macros(
 | 
				
			||||||
 | 
					                                                    vec![Command::UsesMacro(macro_string)],
 | 
				
			||||||
 | 
					                                                    prepare_variables,
 | 
				
			||||||
 | 
					                                                    handler,
 | 
				
			||||||
 | 
					                                                )?;
 | 
				
			||||||
 | 
					                                            move_cmds.extend(cmds);
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    Parameter::Storage {
 | 
					                                    Parameter::Storage {
 | 
				
			||||||
| 
						 | 
					@ -742,15 +748,21 @@ impl Transpiler {
 | 
				
			||||||
                                                return Err(err);
 | 
					                                                return Err(err);
 | 
				
			||||||
                                            }
 | 
					                                            }
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                        Err((parts, preparation_cmds)) => {
 | 
					                                        Err((parts, prepare_cmds)) => {
 | 
				
			||||||
                                            let (macro_string, preparation_variables) = MacroString::MacroString {
 | 
					                                            let (macro_string, prepare_variables) = MacroString::MacroString {
 | 
				
			||||||
                                                parts: std::iter::once(MacroStringPart::String(format!("data modify storage {target_storage_name} {target_path} set value ")))
 | 
					                                                parts: std::iter::once(MacroStringPart::String(format!("data modify storage {target_storage_name} {target_path} set value ")))
 | 
				
			||||||
                                                    .chain(parts.iter().cloned())
 | 
					                                                    .chain(parts.iter().cloned())
 | 
				
			||||||
                                                    .collect(),
 | 
					                                                    .collect(),
 | 
				
			||||||
                                                prepare_variables: preparation_cmds.to_owned(),
 | 
					                                                prepare_variables: prepare_cmds.to_owned(),
 | 
				
			||||||
                                            }
 | 
					                                            }
 | 
				
			||||||
                                            .into_sb();
 | 
					                                            .into_sb();
 | 
				
			||||||
                                            move_cmds.push(Command::UsesMacro(macro_string));
 | 
					                                            let cmds = self
 | 
				
			||||||
 | 
					                                                .transpile_commands_with_variable_macros(
 | 
				
			||||||
 | 
					                                                    vec![Command::UsesMacro(macro_string)],
 | 
				
			||||||
 | 
					                                                    prepare_variables,
 | 
				
			||||||
 | 
					                                                    handler,
 | 
				
			||||||
 | 
					                                                )?;
 | 
				
			||||||
 | 
					                                            move_cmds.extend(cmds);
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    Parameter::Storage {
 | 
					                                    Parameter::Storage {
 | 
				
			||||||
| 
						 | 
					@ -808,10 +820,10 @@ impl Transpiler {
 | 
				
			||||||
                                }),
 | 
					                                }),
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                        let storage_suffix = function_location.replace(['/', ':'], "_");
 | 
					                        let storage_suffix = function_location.replace(['/', ':'], "_");
 | 
				
			||||||
                        let statics_cmd = match joined_statics {
 | 
					                        let statics_cmds = match joined_statics {
 | 
				
			||||||
                            MacroString::String(s) => Command::Raw(format!(
 | 
					                            MacroString::String(s) => vec![Command::Raw(format!(
 | 
				
			||||||
                                r"data merge storage shulkerscript:function_arguments_{storage_suffix} {{{s}}}"
 | 
					                                r"data merge storage shulkerscript:function_arguments_{storage_suffix} {{{s}}}"
 | 
				
			||||||
                            )),
 | 
					                            ))],
 | 
				
			||||||
                            MacroString::MacroString { .. } => {
 | 
					                            MacroString::MacroString { .. } => {
 | 
				
			||||||
                                let prefix = MacroString::String(format!(
 | 
					                                let prefix = MacroString::String(format!(
 | 
				
			||||||
                                    "data merge storage shulkerscript:function_arguments_{storage_suffix} {{"
 | 
					                                    "data merge storage shulkerscript:function_arguments_{storage_suffix} {{"
 | 
				
			||||||
| 
						 | 
					@ -823,10 +835,14 @@ impl Transpiler {
 | 
				
			||||||
                                        MacroString::String("}".to_string()),
 | 
					                                        MacroString::String("}".to_string()),
 | 
				
			||||||
                                    ])
 | 
					                                    ])
 | 
				
			||||||
                                    .into_sb();
 | 
					                                    .into_sb();
 | 
				
			||||||
                                Command::UsesMacro(macro_string)
 | 
					                                self.transpile_commands_with_variable_macros(
 | 
				
			||||||
 | 
					                                    vec![Command::UsesMacro(macro_string)],
 | 
				
			||||||
 | 
					                                    prepare_variables,
 | 
				
			||||||
 | 
					                                    handler,
 | 
				
			||||||
 | 
					                                )?
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
                        setup_cmds.push(statics_cmd);
 | 
					                        setup_cmds.extend(statics_cmds);
 | 
				
			||||||
                        setup_cmds.extend(move_cmds);
 | 
					                        setup_cmds.extend(move_cmds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        Ok(TranspiledFunctionArguments::Dynamic(setup_cmds))
 | 
					                        Ok(TranspiledFunctionArguments::Dynamic(setup_cmds))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -589,8 +589,7 @@ fn print_function(
 | 
				
			||||||
    let cmd = format!("tellraw {target} {print_args}");
 | 
					    let cmd = format!("tellraw {target} {print_args}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let cmd = if contains_macro {
 | 
					    let cmd = if contains_macro {
 | 
				
			||||||
        let (macro_string, prepare_variables) =
 | 
					        let (macro_string, _) = cmd.parse::<MacroString>().expect("cannot fail").into_sb();
 | 
				
			||||||
            cmd.parse::<MacroString>().expect("cannot fail").into_sb();
 | 
					 | 
				
			||||||
        Command::UsesMacro(macro_string)
 | 
					        Command::UsesMacro(macro_string)
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        Command::Raw(cmd)
 | 
					        Command::Raw(cmd)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@ use crate::{
 | 
				
			||||||
        AnnotationAssignment,
 | 
					        AnnotationAssignment,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    transpile::{
 | 
					    transpile::{
 | 
				
			||||||
 | 
					        conversions::ShulkerboxMacroStringMap,
 | 
				
			||||||
        error::IllegalAnnotationContent,
 | 
					        error::IllegalAnnotationContent,
 | 
				
			||||||
        expression::DataLocation,
 | 
					        expression::DataLocation,
 | 
				
			||||||
        util::{MacroString, MacroStringPart},
 | 
					        util::{MacroString, MacroStringPart},
 | 
				
			||||||
| 
						 | 
					@ -471,9 +472,18 @@ impl Transpiler {
 | 
				
			||||||
            .comptime_eval(scope, handler)
 | 
					            .comptime_eval(scope, handler)
 | 
				
			||||||
            .map(|val| val.to_macro_string());
 | 
					            .map(|val| val.to_macro_string());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (prepare_cmds, ret_cmd) = if let Ok(val) = comptime_val {
 | 
					        let (prepare_cmds, ret_cmds) = if let Ok(val) = comptime_val {
 | 
				
			||||||
            let (macro_string, prepare_variables) = val.into_sb();
 | 
					            let (macro_string, prepare_variables) = val.into_sb();
 | 
				
			||||||
            (Vec::new(), datapack::ReturnCommand::Value(macro_string))
 | 
					
 | 
				
			||||||
 | 
					            let cmds = self.transpile_commands_with_variable_macros(
 | 
				
			||||||
 | 
					                vec![Command::Return(datapack::ReturnCommand::Value(
 | 
				
			||||||
 | 
					                    macro_string,
 | 
				
			||||||
 | 
					                ))],
 | 
				
			||||||
 | 
					                prepare_variables,
 | 
				
			||||||
 | 
					                handler,
 | 
				
			||||||
 | 
					            )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            (Vec::new(), cmds)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            match ret.expression() {
 | 
					            match ret.expression() {
 | 
				
			||||||
                Expression::Primary(Primary::Prefix(prefix))
 | 
					                Expression::Primary(Primary::Prefix(prefix))
 | 
				
			||||||
| 
						 | 
					@ -481,12 +491,25 @@ impl Transpiler {
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    let ret_cmds =
 | 
					                    let ret_cmds =
 | 
				
			||||||
                        self.transpile_run_expression(prefix.operand(), scope, handler)?;
 | 
					                        self.transpile_run_expression(prefix.operand(), scope, handler)?;
 | 
				
			||||||
                    let cmd = if ret_cmds.len() == 1 {
 | 
					
 | 
				
			||||||
                        ret_cmds.into_iter().next().unwrap()
 | 
					                    let cmd = match ret_cmds.last() {
 | 
				
			||||||
                    } else {
 | 
					                        _ if ret_cmds.len() == 1 => ret_cmds.into_iter().next().unwrap(),
 | 
				
			||||||
                        Command::Group(Group::new(ret_cmds))
 | 
					                        Some(Command::Group(group)) if group.block_pass_macros().is_some() => {
 | 
				
			||||||
 | 
					                            let block_macros =
 | 
				
			||||||
 | 
					                                group.block_pass_macros().expect("checked above").clone();
 | 
				
			||||||
 | 
					                            Command::Group(
 | 
				
			||||||
 | 
					                                Group::new(ret_cmds).with_block_pass_macros(block_macros),
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        _ => Command::Group(Group::new(ret_cmds)),
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                    (Vec::new(), datapack::ReturnCommand::Command(Box::new(cmd)))
 | 
					
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        Vec::new(),
 | 
				
			||||||
 | 
					                        vec![Command::Return(datapack::ReturnCommand::Command(Box::new(
 | 
				
			||||||
 | 
					                            cmd,
 | 
				
			||||||
 | 
					                        )))],
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Expression::Primary(Primary::FunctionCall(func)) => {
 | 
					                Expression::Primary(Primary::FunctionCall(func)) => {
 | 
				
			||||||
                    let ret_cmds = self.transpile_function_call(func, scope, handler)?;
 | 
					                    let ret_cmds = self.transpile_function_call(func, scope, handler)?;
 | 
				
			||||||
| 
						 | 
					@ -495,16 +518,21 @@ impl Transpiler {
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        Command::Group(Group::new(ret_cmds))
 | 
					                        Command::Group(Group::new(ret_cmds))
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                    (Vec::new(), datapack::ReturnCommand::Command(Box::new(cmd)))
 | 
					                    (
 | 
				
			||||||
 | 
					                        Vec::new(),
 | 
				
			||||||
 | 
					                        vec![Command::Return(datapack::ReturnCommand::Command(Box::new(
 | 
				
			||||||
 | 
					                            cmd,
 | 
				
			||||||
 | 
					                        )))],
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Expression::Primary(Primary::Identifier(ident)) => {
 | 
					                Expression::Primary(Primary::Identifier(ident)) => {
 | 
				
			||||||
                    if let Some(var) = scope.get_variable(ident.span.str()) {
 | 
					                    if let Some(var) = scope.get_variable(ident.span.str()) {
 | 
				
			||||||
                        match var.as_ref() {
 | 
					                        match var.as_ref() {
 | 
				
			||||||
                            VariableData::BooleanStorage { storage_name, path } => (
 | 
					                            VariableData::BooleanStorage { storage_name, path } => (
 | 
				
			||||||
                                Vec::new(),
 | 
					                                Vec::new(),
 | 
				
			||||||
                                datapack::ReturnCommand::Command(Box::new(Command::Raw(format!(
 | 
					                                vec![Command::Return(datapack::ReturnCommand::Command(Box::new(
 | 
				
			||||||
                                    "data get storage {storage_name} {path}"
 | 
					                                    Command::Raw(format!("data get storage {storage_name} {path}")),
 | 
				
			||||||
                                )))),
 | 
					                                )))],
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            VariableData::ComptimeValue {
 | 
					                            VariableData::ComptimeValue {
 | 
				
			||||||
                                value,
 | 
					                                value,
 | 
				
			||||||
| 
						 | 
					@ -518,18 +546,25 @@ impl Transpiler {
 | 
				
			||||||
                                    Err(err)
 | 
					                                    Err(err)
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                                |val| {
 | 
					                                |val| {
 | 
				
			||||||
                                    let cmd = val.to_string_no_macro().map_or_else(
 | 
					                                    let cmds = if let Some(s) = val.to_string_no_macro() {
 | 
				
			||||||
                                        || {
 | 
					                                        vec![Command::Return(datapack::ReturnCommand::Command(
 | 
				
			||||||
                                            let (macro_string, prepare_variables) =
 | 
					                                            Box::new(Command::Raw(s)),
 | 
				
			||||||
                                                val.to_macro_string().into_sb();
 | 
					                                        ))]
 | 
				
			||||||
                                            Command::UsesMacro(macro_string)
 | 
					                                    } else {
 | 
				
			||||||
                                        },
 | 
					                                        let (macro_string, prepare_variables) =
 | 
				
			||||||
                                        Command::Raw,
 | 
					                                            val.to_macro_string().into_sb();
 | 
				
			||||||
                                    );
 | 
					                                        self.transpile_commands_with_variable_macros(
 | 
				
			||||||
                                    Ok((
 | 
					                                            vec![Command::Return(
 | 
				
			||||||
                                        Vec::new(),
 | 
					                                                datapack::ReturnCommand::Command(Box::new(
 | 
				
			||||||
                                        datapack::ReturnCommand::Command(Box::new(cmd)),
 | 
					                                                    Command::UsesMacro(macro_string),
 | 
				
			||||||
                                    ))
 | 
					                                                )),
 | 
				
			||||||
 | 
					                                            )],
 | 
				
			||||||
 | 
					                                            prepare_variables,
 | 
				
			||||||
 | 
					                                            handler,
 | 
				
			||||||
 | 
					                                        )?
 | 
				
			||||||
 | 
					                                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                    Ok((Vec::new(), cmds))
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                            )?,
 | 
					                            )?,
 | 
				
			||||||
                            VariableData::MacroParameter {
 | 
					                            VariableData::MacroParameter {
 | 
				
			||||||
| 
						 | 
					@ -537,19 +572,21 @@ impl Transpiler {
 | 
				
			||||||
                                macro_name,
 | 
					                                macro_name,
 | 
				
			||||||
                            } => (
 | 
					                            } => (
 | 
				
			||||||
                                Vec::new(),
 | 
					                                Vec::new(),
 | 
				
			||||||
                                datapack::ReturnCommand::Command(Box::new(Command::UsesMacro(
 | 
					                                vec![Command::Return(datapack::ReturnCommand::Command(Box::new(
 | 
				
			||||||
                                    shulkerbox::util::MacroString::MacroString(vec![
 | 
					                                    Command::UsesMacro(shulkerbox::util::MacroString::MacroString(
 | 
				
			||||||
                                        shulkerbox::util::MacroStringPart::MacroUsage(
 | 
					                                        vec![shulkerbox::util::MacroStringPart::MacroUsage(
 | 
				
			||||||
                                            macro_name.clone(),
 | 
					                                            macro_name.clone(),
 | 
				
			||||||
                                        ),
 | 
					                                        )],
 | 
				
			||||||
                                    ]),
 | 
					                                    )),
 | 
				
			||||||
                                ))),
 | 
					                                )))],
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            VariableData::ScoreboardValue { objective, target } => (
 | 
					                            VariableData::ScoreboardValue { objective, target } => (
 | 
				
			||||||
                                Vec::new(),
 | 
					                                Vec::new(),
 | 
				
			||||||
                                datapack::ReturnCommand::Command(Box::new(Command::Raw(format!(
 | 
					                                vec![Command::Return(datapack::ReturnCommand::Command(Box::new(
 | 
				
			||||||
                                    "scoreboard players get {target} {objective}"
 | 
					                                    Command::Raw(format!(
 | 
				
			||||||
                                )))),
 | 
					                                        "scoreboard players get {target} {objective}"
 | 
				
			||||||
 | 
					                                    )),
 | 
				
			||||||
 | 
					                                )))],
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            _ => {
 | 
					                            _ => {
 | 
				
			||||||
                                let err = TranspileError::UnexpectedExpression(
 | 
					                                let err = TranspileError::UnexpectedExpression(
 | 
				
			||||||
| 
						 | 
					@ -585,15 +622,12 @@ impl Transpiler {
 | 
				
			||||||
                        scope,
 | 
					                        scope,
 | 
				
			||||||
                        handler,
 | 
					                        handler,
 | 
				
			||||||
                    )?;
 | 
					                    )?;
 | 
				
			||||||
                    (cmds, ret_cmd)
 | 
					                    (cmds, vec![Command::Return(ret_cmd)])
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let cmds = prepare_cmds
 | 
					        let cmds = prepare_cmds.into_iter().chain(ret_cmds).collect();
 | 
				
			||||||
            .into_iter()
 | 
					 | 
				
			||||||
            .chain(std::iter::once(Command::Return(ret_cmd)))
 | 
					 | 
				
			||||||
            .collect();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(cmds)
 | 
					        Ok(cmds)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -849,14 +883,15 @@ impl Transpiler {
 | 
				
			||||||
        scope: &Arc<Scope>,
 | 
					        scope: &Arc<Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<Vec<Command>> {
 | 
					    ) -> TranspileResult<Vec<Command>> {
 | 
				
			||||||
        self.transpile_execute_block_internal(execute, program_identifier, scope, handler)
 | 
					        if let Some((mut pre_cmds, prepare_variables, exec)) =
 | 
				
			||||||
            .map(|ex| {
 | 
					            self.transpile_execute_block_internal(execute, program_identifier, scope, handler)?
 | 
				
			||||||
                ex.map(|(mut pre_cmds, exec)| {
 | 
					        {
 | 
				
			||||||
                    pre_cmds.push(exec.into());
 | 
					            pre_cmds.push(exec.into());
 | 
				
			||||||
                    pre_cmds
 | 
					
 | 
				
			||||||
                })
 | 
					            self.transpile_commands_with_variable_macros(pre_cmds, prepare_variables, handler)
 | 
				
			||||||
                .unwrap_or_default()
 | 
					        } else {
 | 
				
			||||||
            })
 | 
					            Ok(Vec::new())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn transpile_execute_block_internal(
 | 
					    fn transpile_execute_block_internal(
 | 
				
			||||||
| 
						 | 
					@ -865,7 +900,7 @@ impl Transpiler {
 | 
				
			||||||
        program_identifier: &str,
 | 
					        program_identifier: &str,
 | 
				
			||||||
        scope: &Arc<Scope>,
 | 
					        scope: &Arc<Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<Option<(Vec<Command>, Execute)>> {
 | 
					    ) -> TranspileResult<Option<(Vec<Command>, ShulkerboxMacroStringMap, Execute)>> {
 | 
				
			||||||
        match execute {
 | 
					        match execute {
 | 
				
			||||||
            ExecuteBlock::HeadTail(head, tail) => {
 | 
					            ExecuteBlock::HeadTail(head, tail) => {
 | 
				
			||||||
                let tail = match tail {
 | 
					                let tail = match tail {
 | 
				
			||||||
| 
						 | 
					@ -889,7 +924,7 @@ impl Transpiler {
 | 
				
			||||||
                        if commands.is_empty() {
 | 
					                        if commands.is_empty() {
 | 
				
			||||||
                            Ok(None)
 | 
					                            Ok(None)
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            Ok(Some((Vec::new(), Execute::Runs(commands))))
 | 
					                            Ok(Some((Vec::new(), BTreeMap::new(), Execute::Runs(commands))))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    ExecuteBlockTail::ExecuteBlock(_, execute_block) => self
 | 
					                    ExecuteBlockTail::ExecuteBlock(_, execute_block) => self
 | 
				
			||||||
| 
						 | 
					@ -964,7 +999,7 @@ impl Transpiler {
 | 
				
			||||||
        program_identifier: &str,
 | 
					        program_identifier: &str,
 | 
				
			||||||
        scope: &Arc<Scope>,
 | 
					        scope: &Arc<Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<Option<(Vec<Command>, Execute)>> {
 | 
					    ) -> TranspileResult<Option<(Vec<Command>, ShulkerboxMacroStringMap, Execute)>> {
 | 
				
			||||||
        let cond_expression = cond.condition().expression().as_ref();
 | 
					        let cond_expression = cond.condition().expression().as_ref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut errors = Vec::new();
 | 
					        let mut errors = Vec::new();
 | 
				
			||||||
| 
						 | 
					@ -994,28 +1029,29 @@ impl Transpiler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Ok(ComptimeValue::Boolean(value)) = cond_expression.comptime_eval(scope, handler) {
 | 
					        if let Ok(ComptimeValue::Boolean(value)) = cond_expression.comptime_eval(scope, handler) {
 | 
				
			||||||
            if value {
 | 
					            if value {
 | 
				
			||||||
                Ok(Some((Vec::new(), then)))
 | 
					                Ok(Some((Vec::new(), BTreeMap::new(), then)))
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                Ok(el.map(|el| (Vec::new(), el)))
 | 
					                Ok(el.map(|el| (Vec::new(), BTreeMap::new(), el)))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if !errors.is_empty() {
 | 
					            if !errors.is_empty() {
 | 
				
			||||||
                return Err(errors.remove(0));
 | 
					                return Err(errors.remove(0));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let (pre_cond_cmds, cond) =
 | 
					            let (pre_cond_cmds, prepare_variables, cond) =
 | 
				
			||||||
                self.transpile_expression_as_condition(cond_expression, scope, handler)?;
 | 
					                self.transpile_expression_as_condition(cond_expression, scope, handler)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match cond {
 | 
					            match cond {
 | 
				
			||||||
                ExtendedCondition::Runtime(cond) => Ok(Some((
 | 
					                ExtendedCondition::Runtime(cond) => Ok(Some((
 | 
				
			||||||
                    pre_cond_cmds,
 | 
					                    pre_cond_cmds,
 | 
				
			||||||
 | 
					                    prepare_variables,
 | 
				
			||||||
                    Execute::If(cond, Box::new(then), el.map(Box::new)),
 | 
					                    Execute::If(cond, Box::new(then), el.map(Box::new)),
 | 
				
			||||||
                ))),
 | 
					                ))),
 | 
				
			||||||
                ExtendedCondition::Comptime(cond) => {
 | 
					                ExtendedCondition::Comptime(cond) => {
 | 
				
			||||||
                    if cond {
 | 
					                    if cond {
 | 
				
			||||||
                        Ok(Some((Vec::new(), then)))
 | 
					                        Ok(Some((Vec::new(), prepare_variables, then)))
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        Ok(el.map(|el| (Vec::new(), el)))
 | 
					                        Ok(el.map(|el| (Vec::new(), prepare_variables, el)))
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1026,14 +1062,14 @@ impl Transpiler {
 | 
				
			||||||
    fn combine_execute_head_tail(
 | 
					    fn combine_execute_head_tail(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        head: &ExecuteBlockHead,
 | 
					        head: &ExecuteBlockHead,
 | 
				
			||||||
        tail: Option<(Vec<Command>, Execute)>,
 | 
					        tail: Option<(Vec<Command>, ShulkerboxMacroStringMap, Execute)>,
 | 
				
			||||||
        program_identifier: &str,
 | 
					        program_identifier: &str,
 | 
				
			||||||
        scope: &Arc<Scope>,
 | 
					        scope: &Arc<Scope>,
 | 
				
			||||||
        handler: &impl Handler<base::Error>,
 | 
					        handler: &impl Handler<base::Error>,
 | 
				
			||||||
    ) -> TranspileResult<Option<(Vec<Command>, Execute)>> {
 | 
					    ) -> TranspileResult<Option<(Vec<Command>, ShulkerboxMacroStringMap, Execute)>> {
 | 
				
			||||||
        Ok(match head {
 | 
					        Ok(match head {
 | 
				
			||||||
            ExecuteBlockHead::Conditional(cond) => {
 | 
					            ExecuteBlockHead::Conditional(cond) => {
 | 
				
			||||||
                if let Some((mut pre_cmds, tail)) = tail {
 | 
					                if let Some((mut pre_cmds, prepare_variables, tail)) = tail {
 | 
				
			||||||
                    self.transpile_conditional(
 | 
					                    self.transpile_conditional(
 | 
				
			||||||
                        cond,
 | 
					                        cond,
 | 
				
			||||||
                        tail,
 | 
					                        tail,
 | 
				
			||||||
| 
						 | 
					@ -1042,9 +1078,10 @@ impl Transpiler {
 | 
				
			||||||
                        scope,
 | 
					                        scope,
 | 
				
			||||||
                        handler,
 | 
					                        handler,
 | 
				
			||||||
                    )?
 | 
					                    )?
 | 
				
			||||||
                    .map(|(pre_cond_cmds, cond)| {
 | 
					                    .map(|(pre_cond_cmds, mut prep_variables, cond)| {
 | 
				
			||||||
                        pre_cmds.extend(pre_cond_cmds);
 | 
					                        pre_cmds.extend(pre_cond_cmds);
 | 
				
			||||||
                        (pre_cmds, cond)
 | 
					                        prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                        (pre_cmds, prep_variables, cond)
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    None
 | 
					                    None
 | 
				
			||||||
| 
						 | 
					@ -1055,22 +1092,41 @@ impl Transpiler {
 | 
				
			||||||
                    .as_selector()
 | 
					                    .as_selector()
 | 
				
			||||||
                    .to_macro_string(Some(self), scope, handler)?;
 | 
					                    .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = selector.into_sb();
 | 
					                let (macro_string, prepare_variables) = selector.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| (pre_cmds, Execute::As(macro_string, Box::new(tail))))
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::As(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::At(at) => {
 | 
					            ExecuteBlockHead::At(at) => {
 | 
				
			||||||
                let selector = at
 | 
					                let selector = at
 | 
				
			||||||
                    .at_selector()
 | 
					                    .at_selector()
 | 
				
			||||||
                    .to_macro_string(Some(self), scope, handler)?;
 | 
					                    .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = selector.into_sb();
 | 
					                let (macro_string, prepare_variables) = selector.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| (pre_cmds, Execute::At(macro_string, Box::new(tail))))
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::At(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::Align(align) => {
 | 
					            ExecuteBlockHead::Align(align) => {
 | 
				
			||||||
                let align = align
 | 
					                let align = align
 | 
				
			||||||
                    .align_selector()
 | 
					                    .align_selector()
 | 
				
			||||||
                    .to_macro_string(Some(self), scope, handler)?;
 | 
					                    .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = align.into_sb();
 | 
					                let (macro_string, prepare_variables) = align.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| {
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
                    (pre_cmds, Execute::Align(macro_string, Box::new(tail)))
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::Align(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::Anchored(anchored) => {
 | 
					            ExecuteBlockHead::Anchored(anchored) => {
 | 
				
			||||||
| 
						 | 
					@ -1079,8 +1135,13 @@ impl Transpiler {
 | 
				
			||||||
                        .anchored_selector()
 | 
					                        .anchored_selector()
 | 
				
			||||||
                        .to_macro_string(Some(self), scope, handler)?;
 | 
					                        .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = anchor.into_sb();
 | 
					                let (macro_string, prepare_variables) = anchor.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| {
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
                    (pre_cmds, Execute::Anchored(macro_string, Box::new(tail)))
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::Anchored(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::In(r#in) => {
 | 
					            ExecuteBlockHead::In(r#in) => {
 | 
				
			||||||
| 
						 | 
					@ -1088,7 +1149,14 @@ impl Transpiler {
 | 
				
			||||||
                    .in_selector()
 | 
					                    .in_selector()
 | 
				
			||||||
                    .to_macro_string(Some(self), scope, handler)?;
 | 
					                    .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = dimension.into_sb();
 | 
					                let (macro_string, prepare_variables) = dimension.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| (pre_cmds, Execute::In(macro_string, Box::new(tail))))
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::In(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::Positioned(positioned) => {
 | 
					            ExecuteBlockHead::Positioned(positioned) => {
 | 
				
			||||||
                let position =
 | 
					                let position =
 | 
				
			||||||
| 
						 | 
					@ -1096,8 +1164,13 @@ impl Transpiler {
 | 
				
			||||||
                        .positioned_selector()
 | 
					                        .positioned_selector()
 | 
				
			||||||
                        .to_macro_string(Some(self), scope, handler)?;
 | 
					                        .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = position.into_sb();
 | 
					                let (macro_string, prepare_variables) = position.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| {
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
                    (pre_cmds, Execute::Positioned(macro_string, Box::new(tail)))
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::Positioned(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::Rotated(rotated) => {
 | 
					            ExecuteBlockHead::Rotated(rotated) => {
 | 
				
			||||||
| 
						 | 
					@ -1106,8 +1179,13 @@ impl Transpiler {
 | 
				
			||||||
                        .rotated_selector()
 | 
					                        .rotated_selector()
 | 
				
			||||||
                        .to_macro_string(Some(self), scope, handler)?;
 | 
					                        .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = rotation.into_sb();
 | 
					                let (macro_string, prepare_variables) = rotation.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| {
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
                    (pre_cmds, Execute::Rotated(macro_string, Box::new(tail)))
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::Rotated(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::Facing(facing) => {
 | 
					            ExecuteBlockHead::Facing(facing) => {
 | 
				
			||||||
| 
						 | 
					@ -1116,8 +1194,13 @@ impl Transpiler {
 | 
				
			||||||
                        .facing_selector()
 | 
					                        .facing_selector()
 | 
				
			||||||
                        .to_macro_string(Some(self), scope, handler)?;
 | 
					                        .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = facing.into_sb();
 | 
					                let (macro_string, prepare_variables) = facing.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| {
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
                    (pre_cmds, Execute::Facing(macro_string, Box::new(tail)))
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::Facing(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::AsAt(as_at) => {
 | 
					            ExecuteBlockHead::AsAt(as_at) => {
 | 
				
			||||||
| 
						 | 
					@ -1125,22 +1208,41 @@ impl Transpiler {
 | 
				
			||||||
                    .asat_selector()
 | 
					                    .asat_selector()
 | 
				
			||||||
                    .to_macro_string(Some(self), scope, handler)?;
 | 
					                    .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = selector.into_sb();
 | 
					                let (macro_string, prepare_variables) = selector.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| (pre_cmds, Execute::AsAt(macro_string, Box::new(tail))))
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::AsAt(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::On(on) => {
 | 
					            ExecuteBlockHead::On(on) => {
 | 
				
			||||||
                let dimension = on
 | 
					                let dimension = on
 | 
				
			||||||
                    .on_selector()
 | 
					                    .on_selector()
 | 
				
			||||||
                    .to_macro_string(Some(self), scope, handler)?;
 | 
					                    .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = dimension.into_sb();
 | 
					                let (macro_string, prepare_variables) = dimension.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| (pre_cmds, Execute::On(macro_string, Box::new(tail))))
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::On(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::Store(store) => {
 | 
					            ExecuteBlockHead::Store(store) => {
 | 
				
			||||||
                let store = store
 | 
					                let store = store
 | 
				
			||||||
                    .store_selector()
 | 
					                    .store_selector()
 | 
				
			||||||
                    .to_macro_string(Some(self), scope, handler)?;
 | 
					                    .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = store.into_sb();
 | 
					                let (macro_string, prepare_variables) = store.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| {
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
                    (pre_cmds, Execute::Store(macro_string, Box::new(tail)))
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::Store(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ExecuteBlockHead::Summon(summon) => {
 | 
					            ExecuteBlockHead::Summon(summon) => {
 | 
				
			||||||
| 
						 | 
					@ -1149,8 +1251,13 @@ impl Transpiler {
 | 
				
			||||||
                        .summon_selector()
 | 
					                        .summon_selector()
 | 
				
			||||||
                        .to_macro_string(Some(self), scope, handler)?;
 | 
					                        .to_macro_string(Some(self), scope, handler)?;
 | 
				
			||||||
                let (macro_string, prepare_variables) = entity.into_sb();
 | 
					                let (macro_string, prepare_variables) = entity.into_sb();
 | 
				
			||||||
                tail.map(|(pre_cmds, tail)| {
 | 
					                tail.map(|(pre_cmds, mut prep_variables, tail)| {
 | 
				
			||||||
                    (pre_cmds, Execute::Summon(macro_string, Box::new(tail)))
 | 
					                    prep_variables.extend(prepare_variables);
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        pre_cmds,
 | 
				
			||||||
 | 
					                        prep_variables,
 | 
				
			||||||
 | 
					                        Execute::Summon(macro_string, Box::new(tail)),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
| 
						 | 
					@ -1197,9 +1304,9 @@ impl Transpiler {
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            prepare_cmds.push(Command::Group(
 | 
					            prepare_cmds.push(Command::Group(
 | 
				
			||||||
                Group::new(cmds)
 | 
					                Group::new(cmds)
 | 
				
			||||||
                    .always_create_function(true)
 | 
					                    .with_always_create_function(true)
 | 
				
			||||||
                    .block_pass_macros(macro_names)
 | 
					                    .with_block_pass_macros(macro_names)
 | 
				
			||||||
                    .data_storage_name(storage_name),
 | 
					                    .with_data_storage_name(storage_name),
 | 
				
			||||||
            ));
 | 
					            ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Ok(prepare_cmds)
 | 
					            Ok(prepare_cmds)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue