Implement group command refactor function compilation
This commit is contained in:
parent
757ff8a54e
commit
fedb55c50a
|
@ -10,6 +10,7 @@ default = ["zip"]
|
|||
zip = ["dep:zip"]
|
||||
|
||||
[dependencies]
|
||||
chksum-md5 = "0.0.0"
|
||||
getset = "0.1.2"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
serde_json = "1.0.114"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::ops::{BitAnd, BitOr, Deref, Not};
|
||||
use std::ops::{BitAnd, BitOr, Not};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::util::compile::{CompileOptions, MutCompilerState, MutFunctionCompilerState};
|
||||
use crate::util::compile::{CompileOptions, FunctionCompilerState, MutCompilerState};
|
||||
|
||||
use super::Command;
|
||||
|
||||
|
@ -32,7 +32,7 @@ impl Execute {
|
|||
&self,
|
||||
options: &CompileOptions,
|
||||
global_state: &MutCompilerState,
|
||||
function_state: &MutFunctionCompilerState,
|
||||
function_state: &FunctionCompilerState,
|
||||
) -> Vec<String> {
|
||||
if let Self::Run(cmd) = self {
|
||||
cmd.compile(options, global_state, function_state)
|
||||
|
@ -52,7 +52,7 @@ impl Execute {
|
|||
require_grouping: bool,
|
||||
options: &CompileOptions,
|
||||
global_state: &MutCompilerState,
|
||||
function_state: &MutFunctionCompilerState,
|
||||
function_state: &FunctionCompilerState,
|
||||
) -> Vec<String> {
|
||||
match self {
|
||||
Self::Align(align, next) => format_execute(
|
||||
|
@ -172,16 +172,20 @@ impl Execute {
|
|||
global_state,
|
||||
function_state,
|
||||
),
|
||||
Self::Run(command) if !require_grouping => command
|
||||
.compile(options, global_state, function_state)
|
||||
.into_iter()
|
||||
.map(|c| prefix.clone() + "run " + &c)
|
||||
.collect(),
|
||||
Self::Run(command) => Command::Group(vec![command.deref().clone()])
|
||||
Self::Run(command) => match &**command {
|
||||
Command::Execute(ex) => ex.compile_internal(
|
||||
prefix,
|
||||
require_grouping,
|
||||
options,
|
||||
global_state,
|
||||
function_state,
|
||||
),
|
||||
command => command
|
||||
.compile(options, global_state, function_state)
|
||||
.into_iter()
|
||||
.map(|c| prefix.clone() + "run " + &c)
|
||||
.collect(),
|
||||
},
|
||||
Self::Runs(commands) if !require_grouping => commands
|
||||
.iter()
|
||||
.flat_map(|c| c.compile(options, global_state, function_state))
|
||||
|
@ -203,7 +207,7 @@ fn format_execute(
|
|||
require_grouping: bool,
|
||||
options: &CompileOptions,
|
||||
global_state: &MutCompilerState,
|
||||
function_state: &MutFunctionCompilerState,
|
||||
function_state: &FunctionCompilerState,
|
||||
) -> Vec<String> {
|
||||
next.compile_internal(
|
||||
prefix + new,
|
||||
|
@ -221,12 +225,16 @@ fn compile_if_cond(
|
|||
prefix: String,
|
||||
options: &CompileOptions,
|
||||
global_state: &MutCompilerState,
|
||||
function_state: &MutFunctionCompilerState,
|
||||
function_state: &FunctionCompilerState,
|
||||
) -> 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())];
|
||||
let mut group_cmd = match then.clone() {
|
||||
Execute::Run(cmd) => vec![*cmd],
|
||||
Execute::Runs(cmds) => cmds,
|
||||
ex => vec![Command::Execute(ex)],
|
||||
};
|
||||
if el.is_some() {
|
||||
group_cmd.push("data modify storage shulkerbox:cond if_success set value true".into());
|
||||
}
|
||||
|
@ -318,7 +326,7 @@ impl Condition {
|
|||
&self,
|
||||
_options: &CompileOptions,
|
||||
_global_state: &MutCompilerState,
|
||||
_function_state: &MutFunctionCompilerState,
|
||||
_function_state: &FunctionCompilerState,
|
||||
) -> Vec<String> {
|
||||
match self.normalize() {
|
||||
Self::Atom(a) => vec!["if ".to_string() + &a],
|
||||
|
|
|
@ -4,9 +4,10 @@ mod execute;
|
|||
|
||||
pub use execute::{Condition, Execute};
|
||||
|
||||
use chksum_md5 as md5;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::util::compile::{CompileOptions, MutCompilerState, MutFunctionCompilerState};
|
||||
use crate::util::compile::{CompileOptions, FunctionCompilerState, MutCompilerState};
|
||||
|
||||
use super::Function;
|
||||
|
||||
|
@ -34,19 +35,13 @@ impl Command {
|
|||
&self,
|
||||
options: &CompileOptions,
|
||||
global_state: &MutCompilerState,
|
||||
function_state: &MutFunctionCompilerState,
|
||||
function_state: &FunctionCompilerState,
|
||||
) -> Vec<String> {
|
||||
match self {
|
||||
Self::Raw(command) => vec![command.clone()],
|
||||
Self::Debug(message) => compile_debug(message, options),
|
||||
Self::Execute(ex) => ex.compile(options, global_state, function_state),
|
||||
Self::Group(commands) => {
|
||||
// TODO: implement correctly
|
||||
commands
|
||||
.iter()
|
||||
.flat_map(|c| c.compile(options, global_state, function_state))
|
||||
.collect()
|
||||
}
|
||||
Self::Group(commands) => compile_group(commands, options, global_state, function_state),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,3 +72,41 @@ fn compile_debug(message: &str, option: &CompileOptions) -> Vec<String> {
|
|||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_group(
|
||||
commands: &[Command],
|
||||
options: &CompileOptions,
|
||||
global_state: &MutCompilerState,
|
||||
function_state: &FunctionCompilerState,
|
||||
) -> Vec<String> {
|
||||
if commands.len() > 1 {
|
||||
let generated_functions = {
|
||||
let generated_functions = function_state.generated_functions();
|
||||
let amount = generated_functions.get();
|
||||
generated_functions.set(amount + 1);
|
||||
|
||||
amount
|
||||
};
|
||||
|
||||
let function_path = {
|
||||
let pre_hash_path =
|
||||
function_state.path().to_owned() + ":" + &generated_functions.to_string();
|
||||
let hash = md5::hash(pre_hash_path).to_hex_lowercase();
|
||||
|
||||
"sb/".to_string() + function_state.path() + "/" + &hash[..16]
|
||||
};
|
||||
|
||||
let namespace = function_state.namespace();
|
||||
|
||||
let mut function = Function::new(namespace, &function_path);
|
||||
function.get_commands_mut().extend(commands.iter().cloned());
|
||||
function_state.add_function(&function_path, function);
|
||||
|
||||
vec![format!("function {namespace}:{function_path}")]
|
||||
} else {
|
||||
commands
|
||||
.iter()
|
||||
.flat_map(|c| c.compile(options, global_state, function_state))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Function struct and implementation
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
use getset::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -48,13 +46,16 @@ impl Function {
|
|||
}
|
||||
|
||||
/// Compile the function into a virtual file.
|
||||
pub fn compile(&self, options: &CompileOptions, state: &MutCompilerState) -> VFile {
|
||||
let function_state = Mutex::new(FunctionCompilerState::default());
|
||||
|
||||
pub fn compile(
|
||||
&self,
|
||||
options: &CompileOptions,
|
||||
global_state: &MutCompilerState,
|
||||
function_state: &FunctionCompilerState,
|
||||
) -> VFile {
|
||||
let content = self
|
||||
.commands
|
||||
.iter()
|
||||
.flat_map(|c| c.compile(options, state, &function_state))
|
||||
.flat_map(|c| c.compile(options, global_state, function_state))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
VFile::Text(content)
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
util::compile::{CompileOptions, MutCompilerState},
|
||||
util::compile::{CompileOptions, FunctionCompilerState, MutCompilerState},
|
||||
virtual_fs::VFolder,
|
||||
};
|
||||
|
||||
use super::{function::Function, tag::Tag};
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
/// Namespace of a datapack
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -76,16 +79,33 @@ impl Namespace {
|
|||
let mut root_folder = VFolder::new();
|
||||
|
||||
// Compile functions
|
||||
for (path, function) in &self.functions {
|
||||
let mut functions = self
|
||||
.functions
|
||||
.iter()
|
||||
.map(|(name, content)| (name.clone(), content.clone()))
|
||||
.collect::<VecDeque<_>>();
|
||||
|
||||
if !self.main_function.get_commands().is_empty() {
|
||||
functions.push_front(("main".to_string(), self.main_function.clone()));
|
||||
}
|
||||
|
||||
let functions = Arc::new(Mutex::new(functions));
|
||||
|
||||
loop {
|
||||
let Some((path, function)) = ({
|
||||
let mut functions = functions.lock().unwrap();
|
||||
let entry = functions.pop_front();
|
||||
drop(functions);
|
||||
entry
|
||||
}) else {
|
||||
break;
|
||||
};
|
||||
|
||||
let function_state =
|
||||
FunctionCompilerState::new(&path, &self.name, Arc::downgrade(&functions));
|
||||
root_folder.add_file(
|
||||
&format!("functions/{}.mcfunction", path),
|
||||
function.compile(options, state),
|
||||
);
|
||||
}
|
||||
if !self.main_function.get_commands().is_empty() {
|
||||
root_folder.add_file(
|
||||
"functions/main.mcfunction",
|
||||
self.main_function.compile(options, state),
|
||||
function.compile(options, state, &function_state),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
//! Compile options for the compiler.
|
||||
|
||||
use std::sync::Mutex;
|
||||
use std::{
|
||||
cell::Cell,
|
||||
collections::VecDeque,
|
||||
sync::{Mutex, Weak},
|
||||
};
|
||||
|
||||
use getset::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::datapack::Function;
|
||||
|
||||
/// Compile options for the compiler.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CompileOptions {
|
||||
|
@ -24,7 +31,41 @@ pub struct CompilerState {}
|
|||
pub type MutCompilerState = Mutex<CompilerState>;
|
||||
|
||||
/// State of the compiler for each function that can change during compilation.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
pub struct FunctionCompilerState {}
|
||||
/// Mutex for the function compiler state.
|
||||
pub type MutFunctionCompilerState = Mutex<FunctionCompilerState>;
|
||||
#[derive(Debug, Clone, Getters)]
|
||||
pub struct FunctionCompilerState {
|
||||
/// Number of generated functions in the current function.
|
||||
#[get = "pub"]
|
||||
generated_functions: Cell<usize>,
|
||||
/// Path of the current function.
|
||||
#[get = "pub"]
|
||||
path: String,
|
||||
/// Namespace of the current function.
|
||||
#[get = "pub"]
|
||||
namespace: String,
|
||||
/// Queue of functions to be generated.
|
||||
functions: FunctionQueue,
|
||||
}
|
||||
|
||||
type FunctionQueue = Weak<Mutex<VecDeque<(String, Function)>>>;
|
||||
|
||||
impl FunctionCompilerState {
|
||||
/// Create a new function compiler state.
|
||||
pub fn new(path: &str, namespace: &str, functions: FunctionQueue) -> Self {
|
||||
Self {
|
||||
generated_functions: Cell::new(0),
|
||||
namespace: namespace.to_string(),
|
||||
path: path.to_string(),
|
||||
functions,
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a function to the queue.
|
||||
pub fn add_function(&self, name: &str, function: Function) {
|
||||
if let Some(queue) = self.functions.upgrade() {
|
||||
queue
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push_back((name.to_string(), function));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue