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