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