basic implementation of return command

This commit is contained in:
Moritz Hölting 2025-04-07 17:57:36 +02:00
parent ed62e75e89
commit 5c4d340162
3 changed files with 52 additions and 2 deletions

View File

@ -28,6 +28,8 @@ pub fn compile_if_cond(
global_state: &MutCompilerState, global_state: &MutCompilerState,
function_state: &FunctionCompilerState, function_state: &FunctionCompilerState,
) -> Vec<CompiledCommand> { ) -> Vec<CompiledCommand> {
// TODO: special handling for return command
if options.pack_format < 20 { if options.pack_format < 20 {
compile_pre_20_format( compile_pre_20_format(
cond, cond,

View File

@ -36,6 +36,9 @@ pub enum Command {
Group(Vec<Command>), Group(Vec<Command>),
/// Comment to be added to the function /// Comment to be added to the function
Comment(String), Comment(String),
/// Return value
Return(ReturnCommand),
/// Command that is a concatenation of two commands /// Command that is a concatenation of two commands
Concat(Box<Command>, Box<Command>), Concat(Box<Command>, Box<Command>),
} }
@ -65,6 +68,23 @@ impl Command {
Self::Comment(comment) => { Self::Comment(comment) => {
vec![CompiledCommand::new("#".to_string() + comment).with_forbid_prefix(true)] vec![CompiledCommand::new("#".to_string() + comment).with_forbid_prefix(true)]
} }
Self::Return(return_cmd) => match return_cmd {
ReturnCommand::Value(value) => {
vec![CompiledCommand::new(format!("return {}", value.compile()))]
}
ReturnCommand::Command(cmd) => {
let compiled_cmd = Self::Group(vec![*cmd.clone()]).compile(
options,
global_state,
function_state,
);
let compiled_cmd = compiled_cmd
.into_iter()
.next()
.expect("group will always return exactly one command");
vec![compiled_cmd.apply_prefix("return run ")]
}
},
Self::Concat(a, b) => { Self::Concat(a, b) => {
let a = a.compile(options, global_state, function_state); let a = a.compile(options, global_state, function_state);
let b = b.compile(options, global_state, function_state); let b = b.compile(options, global_state, function_state);
@ -97,7 +117,7 @@ impl Command {
Self::Raw(cmd) => cmd.split('\n').count(), Self::Raw(cmd) => cmd.split('\n').count(),
Self::UsesMacro(cmd) => cmd.line_count(), Self::UsesMacro(cmd) => cmd.line_count(),
Self::Execute(ex) => ex.get_count(options), Self::Execute(ex) => ex.get_count(options),
Self::Group(_) => 1, Self::Group(_) | Self::Return(_) => 1,
Self::Concat(a, b) => a.get_count(options) + b.get_count(options) - 1, Self::Concat(a, b) => a.get_count(options) + b.get_count(options) - 1,
} }
} }
@ -110,6 +130,12 @@ impl Command {
Self::Raw(cmd) => validate_raw_cmd(cmd, pack_formats), Self::Raw(cmd) => validate_raw_cmd(cmd, pack_formats),
Self::UsesMacro(cmd) => validate_raw_cmd(&cmd.compile(), pack_formats), Self::UsesMacro(cmd) => validate_raw_cmd(&cmd.compile(), pack_formats),
Self::Execute(ex) => ex.validate(pack_formats), Self::Execute(ex) => ex.validate(pack_formats),
Self::Return(ret) => match ret {
ReturnCommand::Value(_) => pack_formats.start() >= &14,
ReturnCommand::Command(cmd) => {
pack_formats.start() >= &16 && cmd.validate(pack_formats)
}
},
Self::Concat(a, b) => a.validate(pack_formats) && b.validate(pack_formats), Self::Concat(a, b) => a.validate(pack_formats) && b.validate(pack_formats),
}; };
if pack_formats.start() < &16 { if pack_formats.start() < &16 {
@ -127,6 +153,10 @@ impl Command {
Self::UsesMacro(s) | Self::Debug(s) => s.contains_macro(), Self::UsesMacro(s) | Self::Debug(s) => s.contains_macro(),
Self::Group(commands) => group_contains_macro(commands), Self::Group(commands) => group_contains_macro(commands),
Self::Execute(ex) => ex.contains_macro(), Self::Execute(ex) => ex.contains_macro(),
Self::Return(ret) => match ret {
ReturnCommand::Value(value) => value.contains_macro(),
ReturnCommand::Command(cmd) => cmd.contains_macro(),
},
Self::Concat(a, b) => a.contains_macro() || b.contains_macro(), Self::Concat(a, b) => a.contains_macro() || b.contains_macro(),
} }
} }
@ -139,6 +169,10 @@ impl Command {
Self::UsesMacro(s) | Self::Debug(s) => s.get_macros(), Self::UsesMacro(s) | Self::Debug(s) => s.get_macros(),
Self::Group(commands) => group_get_macros(commands), Self::Group(commands) => group_get_macros(commands),
Self::Execute(ex) => ex.get_macros(), Self::Execute(ex) => ex.get_macros(),
Self::Return(ret) => match ret {
ReturnCommand::Value(value) => value.get_macros(),
ReturnCommand::Command(cmd) => cmd.get_macros(),
},
Self::Concat(a, b) => { Self::Concat(a, b) => {
let mut macros = a.get_macros(); let mut macros = a.get_macros();
macros.extend(b.get_macros()); macros.extend(b.get_macros());
@ -154,6 +188,10 @@ impl Command {
Self::Comment(_) => true, Self::Comment(_) => true,
Self::Raw(_) | Self::Debug(_) | Self::Execute(_) | Self::UsesMacro(_) => false, Self::Raw(_) | Self::Debug(_) | Self::Execute(_) | Self::UsesMacro(_) => false,
Self::Group(commands) => commands.len() == 1 && commands[0].forbid_prefix(), Self::Group(commands) => commands.len() == 1 && commands[0].forbid_prefix(),
Self::Return(ret) => match ret {
ReturnCommand::Value(_) => false,
ReturnCommand::Command(cmd) => cmd.forbid_prefix(),
},
Self::Concat(a, _) => a.forbid_prefix(), Self::Concat(a, _) => a.forbid_prefix(),
} }
} }
@ -175,6 +213,16 @@ impl From<&mut Function> for Command {
} }
} }
/// Represents a command that returns a value.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ReturnCommand {
/// Returns the value
Value(MacroString),
/// Returns the result of the command
Command(Box<Command>),
}
fn compile_debug(message: &MacroString, option: &CompileOptions) -> Vec<CompiledCommand> { fn compile_debug(message: &MacroString, option: &CompileOptions) -> Vec<CompiledCommand> {
if option.debug { if option.debug {
vec![CompiledCommand::new(format!( vec![CompiledCommand::new(format!(

View File

@ -4,7 +4,7 @@ mod command;
mod function; mod function;
mod namespace; mod namespace;
pub mod tag; pub mod tag;
pub use command::{Command, Condition, Execute}; pub use command::{Command, Condition, Execute, ReturnCommand};
pub use function::Function; pub use function::Function;
pub use namespace::Namespace; pub use namespace::Namespace;