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