Compare commits
	
		
			No commits in common. "7290806a2bc8eb059a102a68042d6246ee3a0e21" and "863bc784cc4a2dd4fd80c5c77559ff8185487fc5" have entirely different histories.
		
	
	
		
			7290806a2b
			...
			863bc784cc
		
	
		| 
						 | 
				
			
			@ -349,7 +349,7 @@ pub struct LuaCode {
 | 
			
		|||
    left_parenthesis: Punctuation,
 | 
			
		||||
    /// The arguments of the lua code.
 | 
			
		||||
    #[get = "pub"]
 | 
			
		||||
    inputs: Option<ConnectedList<Identifier, Punctuation>>,
 | 
			
		||||
    variables: Option<ConnectedList<Identifier, Punctuation>>,
 | 
			
		||||
    /// The right parenthesis of the lua code.
 | 
			
		||||
    #[get = "pub"]
 | 
			
		||||
    right_parenthesis: Punctuation,
 | 
			
		||||
| 
						 | 
				
			
			@ -550,7 +550,10 @@ impl<'a> Parser<'a> {
 | 
			
		|||
                    Delimiter::Parenthesis,
 | 
			
		||||
                    ',',
 | 
			
		||||
                    |parser| match parser.next_significant_token() {
 | 
			
		||||
                        Reading::Atomic(Token::Identifier(identifier)) => Ok(identifier),
 | 
			
		||||
                        Reading::Atomic(Token::Identifier(identifier)) => {
 | 
			
		||||
                            parser.forward();
 | 
			
		||||
                            Ok(identifier)
 | 
			
		||||
                        }
 | 
			
		||||
                        unexpected => {
 | 
			
		||||
                            let err = Error::UnexpectedSyntax(UnexpectedSyntax {
 | 
			
		||||
                                expected: syntax::error::SyntaxKind::Identifier,
 | 
			
		||||
| 
						 | 
				
			
			@ -594,7 +597,7 @@ impl<'a> Parser<'a> {
 | 
			
		|||
                Ok(Primary::Lua(Box::new(LuaCode {
 | 
			
		||||
                    lua_keyword,
 | 
			
		||||
                    left_parenthesis: variables.open,
 | 
			
		||||
                    inputs: variables.list,
 | 
			
		||||
                    variables: variables.list,
 | 
			
		||||
                    right_parenthesis: variables.close,
 | 
			
		||||
                    left_brace: tree.open,
 | 
			
		||||
                    code: tree.tree?,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,50 +1,57 @@
 | 
			
		|||
//! Conversion functions for converting between tokens/ast-nodes and [`shulkerbox`] types
 | 
			
		||||
 | 
			
		||||
use shulkerbox::util::{MacroString as ExtMacroString, MacroStringPart as ExtMacroStringPart};
 | 
			
		||||
use shulkerbox::util::{MacroString, MacroStringPart};
 | 
			
		||||
 | 
			
		||||
use crate::{lexical::token::MacroStringLiteral, syntax::syntax_tree::AnyStringLiteral};
 | 
			
		||||
use crate::{
 | 
			
		||||
    lexical::token::{MacroStringLiteral, MacroStringLiteralPart},
 | 
			
		||||
    syntax::syntax_tree::AnyStringLiteral,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use super::util::{MacroString, MacroStringPart};
 | 
			
		||||
 | 
			
		||||
impl From<MacroString> for ExtMacroString {
 | 
			
		||||
    fn from(value: MacroString) -> Self {
 | 
			
		||||
        match value {
 | 
			
		||||
            MacroString::String(s) => Self::String(s),
 | 
			
		||||
            MacroString::MacroString(parts) => {
 | 
			
		||||
                Self::MacroString(parts.into_iter().map(ExtMacroStringPart::from).collect())
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<MacroStringPart> for ExtMacroStringPart {
 | 
			
		||||
    fn from(value: MacroStringPart) -> Self {
 | 
			
		||||
        match value {
 | 
			
		||||
            MacroStringPart::String(s) => Self::String(s),
 | 
			
		||||
            MacroStringPart::MacroUsage(m) => Self::MacroUsage(m),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<&AnyStringLiteral> for ExtMacroString {
 | 
			
		||||
impl From<&AnyStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: &AnyStringLiteral) -> Self {
 | 
			
		||||
        Self::from(MacroString::from(value))
 | 
			
		||||
        match value {
 | 
			
		||||
            AnyStringLiteral::StringLiteral(literal) => Self::from(literal.str_content().as_ref()),
 | 
			
		||||
            AnyStringLiteral::MacroStringLiteral(literal) => Self::from(literal),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<AnyStringLiteral> for ExtMacroString {
 | 
			
		||||
impl From<AnyStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: AnyStringLiteral) -> Self {
 | 
			
		||||
        Self::from(&value)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<&MacroStringLiteral> for ExtMacroString {
 | 
			
		||||
impl From<&MacroStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: &MacroStringLiteral) -> Self {
 | 
			
		||||
        Self::from(MacroString::from(value))
 | 
			
		||||
        if value
 | 
			
		||||
            .parts()
 | 
			
		||||
            .iter()
 | 
			
		||||
            .any(|p| matches!(p, MacroStringLiteralPart::MacroUsage { .. }))
 | 
			
		||||
        {
 | 
			
		||||
            Self::MacroString(
 | 
			
		||||
                value
 | 
			
		||||
                    .parts()
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .map(|part| match part {
 | 
			
		||||
                        MacroStringLiteralPart::Text(span) => MacroStringPart::String(
 | 
			
		||||
                            crate::util::unescape_macro_string(span.str()).to_string(),
 | 
			
		||||
                        ),
 | 
			
		||||
                        MacroStringLiteralPart::MacroUsage { identifier, .. } => {
 | 
			
		||||
                            MacroStringPart::MacroUsage(
 | 
			
		||||
                                crate::util::identifier_to_macro(identifier.span.str()).to_string(),
 | 
			
		||||
                            )
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                    .collect(),
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            Self::String(value.str_content())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<MacroStringLiteral> for ExtMacroString {
 | 
			
		||||
impl From<MacroStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: MacroStringLiteral) -> Self {
 | 
			
		||||
        Self::from(&value)
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 | 
			
		||||
use std::{fmt::Display, sync::Arc};
 | 
			
		||||
 | 
			
		||||
use super::{util::MacroString, Scope, VariableData};
 | 
			
		||||
use super::{Scope, VariableData};
 | 
			
		||||
use crate::{
 | 
			
		||||
    base::{self, Handler, VoidHandler},
 | 
			
		||||
    lexical::token::MacroStringLiteralPart,
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,10 @@ use crate::{
 | 
			
		|||
use enum_as_inner::EnumAsInner;
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "shulkerbox")]
 | 
			
		||||
use shulkerbox::prelude::{Command, Condition, Execute};
 | 
			
		||||
use shulkerbox::{
 | 
			
		||||
    prelude::{Command, Condition, Execute},
 | 
			
		||||
    util::MacroString,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "shulkerbox")]
 | 
			
		||||
use super::{
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +51,7 @@ impl Display for ComptimeValue {
 | 
			
		|||
            Self::Boolean(boolean) => write!(f, "{boolean}"),
 | 
			
		||||
            Self::Integer(int) => write!(f, "{int}"),
 | 
			
		||||
            Self::String(string) => write!(f, "{string}"),
 | 
			
		||||
            Self::MacroString(macro_string) => write!(f, "{macro_string}"),
 | 
			
		||||
            Self::MacroString(macro_string) => write!(f, "{}", macro_string.compile()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +296,7 @@ impl Primary {
 | 
			
		|||
            Self::Lua(lua) => {
 | 
			
		||||
                cfg_if::cfg_if! {
 | 
			
		||||
                    if #[cfg(feature = "lua")] {
 | 
			
		||||
                        lua.eval(scope, &VoidHandler).map_or(false, |(value, _)| match value {
 | 
			
		||||
                        lua.eval(&VoidHandler).map_or(false, |value| match value {
 | 
			
		||||
                            mlua::Value::Boolean(_) => matches!(r#type, ValueType::Boolean),
 | 
			
		||||
                            mlua::Value::Integer(_) => matches!(r#type, ValueType::Integer),
 | 
			
		||||
                            mlua::Value::String(_) => matches!(r#type, ValueType::String),
 | 
			
		||||
| 
						 | 
				
			
			@ -342,7 +345,7 @@ impl Primary {
 | 
			
		|||
                    })
 | 
			
		||||
            }
 | 
			
		||||
            Self::Lua(lua) => lua
 | 
			
		||||
                .eval_comptime(scope, &VoidHandler)
 | 
			
		||||
                .eval_comptime(&VoidHandler)
 | 
			
		||||
                .inspect_err(|err| {
 | 
			
		||||
                    handler.receive(err.clone());
 | 
			
		||||
                })
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +621,7 @@ impl Transpiler {
 | 
			
		|||
            Primary::Lua(lua) =>
 | 
			
		||||
            {
 | 
			
		||||
                #[expect(clippy::option_if_let_else)]
 | 
			
		||||
                if let Some(value) = lua.eval_comptime(scope, handler)? {
 | 
			
		||||
                if let Some(value) = lua.eval_comptime(handler)? {
 | 
			
		||||
                    self.store_comptime_value(&value, target, lua, handler)
 | 
			
		||||
                } else {
 | 
			
		||||
                    let err = TranspileError::MissingValue(MissingValue {
 | 
			
		||||
| 
						 | 
				
			
			@ -1030,14 +1033,14 @@ impl Transpiler {
 | 
			
		|||
                    Err(err)
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            Primary::Lua(lua) => match lua.eval_comptime(scope, handler)? {
 | 
			
		||||
            Primary::Lua(lua) => match lua.eval_comptime(handler)? {
 | 
			
		||||
                Some(ComptimeValue::String(value)) => Ok((
 | 
			
		||||
                    Vec::new(),
 | 
			
		||||
                    ExtendedCondition::Runtime(Condition::Atom(value.into())),
 | 
			
		||||
                )),
 | 
			
		||||
                Some(ComptimeValue::MacroString(value)) => Ok((
 | 
			
		||||
                    Vec::new(),
 | 
			
		||||
                    ExtendedCondition::Runtime(Condition::Atom(value.into())),
 | 
			
		||||
                    ExtendedCondition::Runtime(Condition::Atom(value)),
 | 
			
		||||
                )),
 | 
			
		||||
                Some(ComptimeValue::Boolean(boolean)) => {
 | 
			
		||||
                    Ok((Vec::new(), ExtendedCondition::Comptime(boolean)))
 | 
			
		||||
| 
						 | 
				
			
			@ -1394,7 +1397,7 @@ impl Transpiler {
 | 
			
		|||
                        ..
 | 
			
		||||
                    }
 | 
			
		||||
                    | DataLocation::Tag { .. } => self.store_condition_success(
 | 
			
		||||
                        ExtendedCondition::Runtime(Condition::Atom(value.clone().into())),
 | 
			
		||||
                        ExtendedCondition::Runtime(Condition::Atom(value.clone())),
 | 
			
		||||
                        target,
 | 
			
		||||
                        source,
 | 
			
		||||
                        handler,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,6 @@
 | 
			
		|||
 | 
			
		||||
#[cfg(feature = "lua")]
 | 
			
		||||
mod enabled {
 | 
			
		||||
    use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
    use mlua::{Lua, Value};
 | 
			
		||||
 | 
			
		||||
    use crate::{
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +10,6 @@ mod enabled {
 | 
			
		|||
        transpile::{
 | 
			
		||||
            error::{LuaRuntimeError, TranspileError, TranspileResult},
 | 
			
		||||
            expression::ComptimeValue,
 | 
			
		||||
            Scope, VariableData,
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,11 +19,7 @@ mod enabled {
 | 
			
		|||
        /// # Errors
 | 
			
		||||
        /// - If evaluation fails
 | 
			
		||||
        #[tracing::instrument(level = "debug", name = "eval_lua", skip_all, ret)]
 | 
			
		||||
        pub fn eval(
 | 
			
		||||
            &self,
 | 
			
		||||
            scope: &Arc<Scope>,
 | 
			
		||||
            handler: &impl Handler<base::Error>,
 | 
			
		||||
        ) -> TranspileResult<(mlua::Value, mlua::Lua)> {
 | 
			
		||||
        pub fn eval(&self, handler: &impl Handler<base::Error>) -> TranspileResult<mlua::Value> {
 | 
			
		||||
            tracing::debug!("Evaluating Lua code");
 | 
			
		||||
 | 
			
		||||
            let lua = Lua::new();
 | 
			
		||||
| 
						 | 
				
			
			@ -53,17 +46,9 @@ mod enabled {
 | 
			
		|||
                )
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if let Err(err) = self.add_globals(&lua, scope) {
 | 
			
		||||
                let err = TranspileError::LuaRuntimeError(LuaRuntimeError::from_lua_err(
 | 
			
		||||
                    &err,
 | 
			
		||||
                    self.span(),
 | 
			
		||||
                ));
 | 
			
		||||
                handler.receive(crate::Error::from(err.clone()));
 | 
			
		||||
                return Err(err);
 | 
			
		||||
            }
 | 
			
		||||
            self.add_globals(&lua).unwrap();
 | 
			
		||||
 | 
			
		||||
            let res = lua
 | 
			
		||||
                .load(self.code())
 | 
			
		||||
            lua.load(self.code())
 | 
			
		||||
                .set_name(name)
 | 
			
		||||
                .eval::<Value>()
 | 
			
		||||
                .map_err(|err| {
 | 
			
		||||
| 
						 | 
				
			
			@ -71,12 +56,7 @@ mod enabled {
 | 
			
		|||
                        TranspileError::from(LuaRuntimeError::from_lua_err(&err, self.span()));
 | 
			
		||||
                    handler.receive(crate::Error::from(err.clone()));
 | 
			
		||||
                    err
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            res.map(|v| {
 | 
			
		||||
                tracing::debug!("Lua code evaluated successfully");
 | 
			
		||||
                (v, lua)
 | 
			
		||||
            })
 | 
			
		||||
                })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// Evaluates the Lua code and returns the resulting [`ComptimeValue`].
 | 
			
		||||
| 
						 | 
				
			
			@ -86,16 +66,17 @@ mod enabled {
 | 
			
		|||
        #[tracing::instrument(level = "debug", name = "eval_lua", skip_all, ret)]
 | 
			
		||||
        pub fn eval_comptime(
 | 
			
		||||
            &self,
 | 
			
		||||
            scope: &Arc<Scope>,
 | 
			
		||||
            handler: &impl Handler<base::Error>,
 | 
			
		||||
        ) -> TranspileResult<Option<ComptimeValue>> {
 | 
			
		||||
            // required to keep the lua instance alive
 | 
			
		||||
            let (lua_result, _lua) = self.eval(scope, handler)?;
 | 
			
		||||
            let lua_result = self.eval(handler)?;
 | 
			
		||||
 | 
			
		||||
            self.handle_lua_result(lua_result, handler)
 | 
			
		||||
                .inspect_err(|err| {
 | 
			
		||||
                    handler.receive(err.clone());
 | 
			
		||||
                })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn add_globals(&self, lua: &Lua, scope: &Arc<Scope>) -> mlua::Result<()> {
 | 
			
		||||
        fn add_globals(&self, lua: &Lua) -> mlua::Result<()> {
 | 
			
		||||
            let globals = lua.globals();
 | 
			
		||||
 | 
			
		||||
            let location = {
 | 
			
		||||
| 
						 | 
				
			
			@ -105,32 +86,6 @@ mod enabled {
 | 
			
		|||
            };
 | 
			
		||||
            globals.set("shu_location", location.to_string_lossy())?;
 | 
			
		||||
 | 
			
		||||
            if let Some(inputs) = self.inputs() {
 | 
			
		||||
                for x in inputs.elements() {
 | 
			
		||||
                    let name = x.span.str();
 | 
			
		||||
                    let value = match scope.get_variable(name).as_deref() {
 | 
			
		||||
                        Some(VariableData::MacroParameter { macro_name, .. }) => {
 | 
			
		||||
                            Value::String(lua.create_string(format!("$({macro_name})"))?)
 | 
			
		||||
                        }
 | 
			
		||||
                        Some(VariableData::ScoreboardValue { objective, target }) => {
 | 
			
		||||
                            let table = lua.create_table()?;
 | 
			
		||||
                            table.set("objective", lua.create_string(objective)?)?;
 | 
			
		||||
                            table.set("target", lua.create_string(target)?)?;
 | 
			
		||||
                            Value::Table(table)
 | 
			
		||||
                        }
 | 
			
		||||
                        Some(VariableData::BooleanStorage { storage_name, path }) => {
 | 
			
		||||
                            let table = lua.create_table()?;
 | 
			
		||||
                            table.set("storage", lua.create_string(storage_name)?)?;
 | 
			
		||||
                            table.set("path", lua.create_string(path)?)?;
 | 
			
		||||
                            Value::Table(table)
 | 
			
		||||
                        }
 | 
			
		||||
                        Some(_) => todo!("allow other types"),
 | 
			
		||||
                        None => todo!("throw correct error"),
 | 
			
		||||
                    };
 | 
			
		||||
                    globals.set(name, value)?;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Ok(())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -175,15 +130,13 @@ mod enabled {
 | 
			
		|||
 | 
			
		||||
#[cfg(not(feature = "lua"))]
 | 
			
		||||
mod disabled {
 | 
			
		||||
    use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
    use crate::{
 | 
			
		||||
        base::{self, Handler},
 | 
			
		||||
        syntax::syntax_tree::expression::LuaCode,
 | 
			
		||||
        transpile::error::{TranspileError, TranspileResult},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    use crate::transpile::{expression::ComptimeValue, Scope};
 | 
			
		||||
    use crate::transpile::expression::ComptimeValue;
 | 
			
		||||
 | 
			
		||||
    impl LuaCode {
 | 
			
		||||
        /// Will always return an error because Lua code evaluation is disabled.
 | 
			
		||||
| 
						 | 
				
			
			@ -192,12 +145,7 @@ mod disabled {
 | 
			
		|||
        /// # Errors
 | 
			
		||||
        /// - Always, as the lua feature is disabled
 | 
			
		||||
        #[tracing::instrument(level = "debug", name = "eval_lua", skip_all, ret)]
 | 
			
		||||
        pub fn eval(
 | 
			
		||||
            &self,
 | 
			
		||||
            scope: &Arc<Scope>,
 | 
			
		||||
            handler: &impl Handler<base::Error>,
 | 
			
		||||
        ) -> TranspileResult<()> {
 | 
			
		||||
            let _ = scope;
 | 
			
		||||
        pub fn eval(&self, handler: &impl Handler<base::Error>) -> TranspileResult<()> {
 | 
			
		||||
            handler.receive(TranspileError::LuaDisabled);
 | 
			
		||||
            tracing::error!("Lua code evaluation is disabled");
 | 
			
		||||
            Err(TranspileError::LuaDisabled)
 | 
			
		||||
| 
						 | 
				
			
			@ -210,10 +158,8 @@ mod disabled {
 | 
			
		|||
        /// - If Lua code evaluation is disabled.
 | 
			
		||||
        pub fn eval_comptime(
 | 
			
		||||
            &self,
 | 
			
		||||
            scope: &Arc<Scope>,
 | 
			
		||||
            handler: &impl Handler<base::Error>,
 | 
			
		||||
        ) -> TranspileResult<Option<ComptimeValue>> {
 | 
			
		||||
            let _ = scope;
 | 
			
		||||
            handler.receive(TranspileError::LuaDisabled);
 | 
			
		||||
            tracing::error!("Lua code evaluation is disabled");
 | 
			
		||||
            Err(TranspileError::LuaDisabled)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,10 @@ use std::{
 | 
			
		|||
    sync::{Arc, OnceLock},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use shulkerbox::datapack::{self, Command, Datapack, Execute};
 | 
			
		||||
use shulkerbox::{
 | 
			
		||||
    datapack::{self, Command, Datapack, Execute},
 | 
			
		||||
    util::{MacroString, MacroStringPart},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    base::{
 | 
			
		||||
| 
						 | 
				
			
			@ -27,10 +30,7 @@ use crate::{
 | 
			
		|||
        },
 | 
			
		||||
        AnnotationAssignment,
 | 
			
		||||
    },
 | 
			
		||||
    transpile::{
 | 
			
		||||
        error::{IllegalAnnotationContent, MissingFunctionDeclaration},
 | 
			
		||||
        util::{MacroString, MacroStringPart},
 | 
			
		||||
    },
 | 
			
		||||
    transpile::error::{IllegalAnnotationContent, MissingFunctionDeclaration},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use super::{
 | 
			
		||||
| 
						 | 
				
			
			@ -439,7 +439,7 @@ impl Transpiler {
 | 
			
		|||
                for expression in arguments.iter().flat_map(|x| x.iter()) {
 | 
			
		||||
                    let value = match expression {
 | 
			
		||||
                        Expression::Primary(Primary::Lua(lua)) => {
 | 
			
		||||
                            lua.eval_comptime(scope, handler).and_then(|val| match val {
 | 
			
		||||
                            lua.eval_comptime(handler).and_then(|val| match val {
 | 
			
		||||
                                Some(ComptimeValue::MacroString(s)) => Ok(Parameter::Static(s)),
 | 
			
		||||
                                Some(val) => Ok(Parameter::Static(val.to_string().into())),
 | 
			
		||||
                                None => {
 | 
			
		||||
| 
						 | 
				
			
			@ -604,17 +604,16 @@ impl Transpiler {
 | 
			
		|||
                        MacroString::String(s) => Command::Raw(format!(
 | 
			
		||||
                            r#"data merge storage shulkerscript:function_arguments {{{s}}}"#
 | 
			
		||||
                        )),
 | 
			
		||||
                        MacroString::MacroString(_) => Command::UsesMacro(
 | 
			
		||||
                            super::util::join_macro_strings([
 | 
			
		||||
                        MacroString::MacroString(_) => {
 | 
			
		||||
                            Command::UsesMacro(super::util::join_macro_strings([
 | 
			
		||||
                                MacroString::String(
 | 
			
		||||
                                    "data merge storage shulkerscript:function_arguments {"
 | 
			
		||||
                                        .to_string(),
 | 
			
		||||
                                ),
 | 
			
		||||
                                joined_statics,
 | 
			
		||||
                                MacroString::String("}".to_string()),
 | 
			
		||||
                            ])
 | 
			
		||||
                            .into(),
 | 
			
		||||
                        ),
 | 
			
		||||
                            ]))
 | 
			
		||||
                        }
 | 
			
		||||
                    };
 | 
			
		||||
                    setup_cmds.push(statics_cmd);
 | 
			
		||||
                    setup_cmds.extend(move_cmds);
 | 
			
		||||
| 
						 | 
				
			
			@ -783,9 +782,9 @@ impl Transpiler {
 | 
			
		|||
            Expression::Primary(Primary::MacroStringLiteral(string)) => {
 | 
			
		||||
                Ok(vec![Command::UsesMacro(string.into())])
 | 
			
		||||
            }
 | 
			
		||||
            Expression::Primary(Primary::Lua(code)) => match code.eval_comptime(scope, handler)? {
 | 
			
		||||
            Expression::Primary(Primary::Lua(code)) => match code.eval_comptime(handler)? {
 | 
			
		||||
                Some(ComptimeValue::String(cmd)) => Ok(vec![Command::Raw(cmd)]),
 | 
			
		||||
                Some(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd.into())]),
 | 
			
		||||
                Some(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd)]),
 | 
			
		||||
                Some(ComptimeValue::Boolean(_) | ComptimeValue::Integer(_)) => {
 | 
			
		||||
                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
			
		||||
                        expected_type: ExpectedType::String,
 | 
			
		||||
| 
						 | 
				
			
			@ -806,7 +805,7 @@ impl Transpiler {
 | 
			
		|||
                ),
 | 
			
		||||
            Expression::Binary(bin) => match bin.comptime_eval(scope, handler) {
 | 
			
		||||
                Some(ComptimeValue::String(cmd)) => Ok(vec![Command::Raw(cmd)]),
 | 
			
		||||
                Some(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd.into())]),
 | 
			
		||||
                Some(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd)]),
 | 
			
		||||
                _ => {
 | 
			
		||||
                    let err = TranspileError::MismatchedTypes(MismatchedTypes {
 | 
			
		||||
                        expression: bin.span(),
 | 
			
		||||
| 
						 | 
				
			
			@ -871,7 +870,7 @@ impl Transpiler {
 | 
			
		|||
                        function_call.push_str(" {");
 | 
			
		||||
                        parts.insert(0, MacroStringPart::String(function_call));
 | 
			
		||||
                        parts.push(MacroStringPart::String('}'.to_string()));
 | 
			
		||||
                        Command::UsesMacro(MacroString::MacroString(parts).into())
 | 
			
		||||
                        Command::UsesMacro(MacroString::MacroString(parts))
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,48 +1,6 @@
 | 
			
		|||
//! Utility methods for transpiling
 | 
			
		||||
 | 
			
		||||
use std::fmt::Display;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    lexical::token::{MacroStringLiteral, MacroStringLiteralPart},
 | 
			
		||||
    syntax::syntax_tree::AnyStringLiteral,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// String that can contain macros
 | 
			
		||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 | 
			
		||||
pub enum MacroString {
 | 
			
		||||
    /// A normal string
 | 
			
		||||
    String(String),
 | 
			
		||||
    /// A string containing macros
 | 
			
		||||
    MacroString(Vec<MacroStringPart>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Part of a [`MacroString`]
 | 
			
		||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 | 
			
		||||
pub enum MacroStringPart {
 | 
			
		||||
    /// A normal string
 | 
			
		||||
    String(String),
 | 
			
		||||
    /// A macro usage
 | 
			
		||||
    MacroUsage(String),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Display for MacroString {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::String(s) => s.fmt(f),
 | 
			
		||||
            Self::MacroString(parts) => {
 | 
			
		||||
                for part in parts {
 | 
			
		||||
                    match part {
 | 
			
		||||
                        MacroStringPart::String(s) => s.fmt(f)?,
 | 
			
		||||
                        MacroStringPart::MacroUsage(m) => write!(f, "$({m})")?,
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                Ok(())
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
use shulkerbox::util::{MacroString, MacroStringPart};
 | 
			
		||||
 | 
			
		||||
fn normalize_program_identifier<S>(identifier: S) -> String
 | 
			
		||||
where
 | 
			
		||||
| 
						 | 
				
			
			@ -113,62 +71,3 @@ where
 | 
			
		|||
            },
 | 
			
		||||
        })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<S> From<S> for MacroString
 | 
			
		||||
where
 | 
			
		||||
    S: Into<String>,
 | 
			
		||||
{
 | 
			
		||||
    fn from(value: S) -> Self {
 | 
			
		||||
        Self::String(value.into())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<&AnyStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: &AnyStringLiteral) -> Self {
 | 
			
		||||
        match value {
 | 
			
		||||
            AnyStringLiteral::StringLiteral(literal) => Self::from(literal.str_content().as_ref()),
 | 
			
		||||
            AnyStringLiteral::MacroStringLiteral(literal) => Self::from(literal),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<AnyStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: AnyStringLiteral) -> Self {
 | 
			
		||||
        Self::from(&value)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<&MacroStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: &MacroStringLiteral) -> Self {
 | 
			
		||||
        if value
 | 
			
		||||
            .parts()
 | 
			
		||||
            .iter()
 | 
			
		||||
            .any(|p| matches!(p, MacroStringLiteralPart::MacroUsage { .. }))
 | 
			
		||||
        {
 | 
			
		||||
            Self::MacroString(
 | 
			
		||||
                value
 | 
			
		||||
                    .parts()
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .map(|part| match part {
 | 
			
		||||
                        MacroStringLiteralPart::Text(span) => MacroStringPart::String(
 | 
			
		||||
                            crate::util::unescape_macro_string(span.str()).to_string(),
 | 
			
		||||
                        ),
 | 
			
		||||
                        MacroStringLiteralPart::MacroUsage { identifier, .. } => {
 | 
			
		||||
                            MacroStringPart::MacroUsage(
 | 
			
		||||
                                crate::util::identifier_to_macro(identifier.span.str()).to_string(),
 | 
			
		||||
                            )
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                    .collect(),
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            Self::String(value.str_content())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<MacroStringLiteral> for MacroString {
 | 
			
		||||
    fn from(value: MacroStringLiteral) -> Self {
 | 
			
		||||
        Self::from(&value)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue