Correctly implement if/else

- Group command working correctly is required but not implemented yet
This commit is contained in:
Moritz Hölting 2024-04-01 20:57:21 +02:00
parent c494031163
commit 757ff8a54e
2 changed files with 93 additions and 41 deletions

View File

@ -34,6 +34,9 @@ impl Execute {
global_state: &MutCompilerState,
function_state: &MutFunctionCompilerState,
) -> Vec<String> {
if let Self::Run(cmd) = self {
cmd.compile(options, global_state, function_state)
} else {
self.compile_internal(
String::from("execute "),
false,
@ -42,6 +45,7 @@ impl Execute {
function_state,
)
}
}
fn compile_internal(
&self,
prefix: String,
@ -159,40 +163,15 @@ impl Execute {
global_state,
function_state,
),
Self::If(cond, then, el) => {
// TODO: group commands if needed and only run else commands if the first commands have not executed
let str_cond = cond.clone().compile(options, global_state, function_state);
let require_grouping = str_cond.len() > 1;
let then = then.compile_internal(
String::new(),
require_grouping,
Self::If(cond, then, el) => compile_if_cond(
cond,
then.as_ref(),
el.as_deref(),
prefix,
options,
global_state,
function_state,
);
let then_commands = combine_conditions_commands(str_cond, then);
let el = el
.as_deref()
.map(|el| {
let else_cond =
(!cond.clone()).compile(options, global_state, function_state);
let el = el.compile_internal(
String::new(),
else_cond.len() > 1,
options,
global_state,
function_state,
);
combine_conditions_commands(else_cond, el)
})
.unwrap_or_default();
then_commands
.into_iter()
.chain(el)
.map(|cmd| prefix.clone() + &cmd + " ")
.collect()
}
),
Self::Run(command) if !require_grouping => command
.compile(options, global_state, function_state)
.into_iter()
@ -235,6 +214,74 @@ fn format_execute(
)
}
fn compile_if_cond(
cond: &Condition,
then: &Execute,
el: Option<&Execute>,
prefix: String,
options: &CompileOptions,
global_state: &MutCompilerState,
function_state: &MutFunctionCompilerState,
) -> Vec<String> {
let str_cond = cond.clone().compile(options, global_state, function_state);
let require_grouping = el.is_some() || str_cond.len() > 1;
let then = if require_grouping {
let mut group_cmd = vec![Command::Execute(then.clone())];
if el.is_some() {
group_cmd.push("data modify storage shulkerbox:cond if_success set value true".into());
}
Command::Group(group_cmd)
.compile(options, global_state, function_state)
.iter()
.map(|s| "run ".to_string() + s)
.collect()
} else {
then.compile_internal(
String::new(),
require_grouping,
options,
global_state,
function_state,
)
};
let then_commands = combine_conditions_commands(str_cond, then);
let el = el
.map(|el| {
let else_cond =
(!Condition::Atom("data storage shulkerbox:cond {if_success:1b}".to_string()))
.compile(options, global_state, function_state);
let el = el.compile_internal(
String::new(),
else_cond.len() > 1,
options,
global_state,
function_state,
);
combine_conditions_commands(else_cond, el)
.into_iter()
.map(|cmd| (true, cmd))
.chain(std::iter::once((
false,
"data remove storage shulkerbox:cond if_success".to_string(),
)))
.map(|(use_prefix, cmd)| {
if use_prefix {
prefix.clone() + &cmd
} else {
cmd
}
})
.collect::<Vec<_>>()
})
.unwrap_or_default();
then_commands
.into_iter()
.map(|cmd| prefix.clone() + &cmd)
.chain(el)
.collect()
}
fn combine_conditions_commands(conditions: Vec<String>, commands: Vec<String>) -> Vec<String> {
conditions
.into_iter()

View File

@ -42,6 +42,11 @@ impl Function {
&self.commands
}
/// Mutably get the commands of the function.
pub fn get_commands_mut(&mut self) -> &mut Vec<Command> {
&mut self.commands
}
/// Compile the function into a virtual file.
pub fn compile(&self, options: &CompileOptions, state: &MutCompilerState) -> VFile {
let function_state = Mutex::new(FunctionCompilerState::default());