1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
use std::{
cmp::Ordering,
collections::VecDeque,
ops::{Deref, DerefMut},
};
use crate::{
block_id::BlockId,
item_id::ItemId,
llir_nodes::{Condition, Node},
minecraft_utils::ScoreboardValue,
};
use super::NodeId;
/// Optimizing functions output commands that tell the optimizer what to do,
/// this is done so that there are no troubles with mutability
#[derive(Debug)]
pub enum OptimizeCommandKind {
/// Deletes a single node
Delete,
/// Converts the [FastStoreFromResult](crate::llir_nodes::FastStoreFromResult) node into its command, discarding
/// the result
DiscardResult,
/// Discards the node and only keeps the branch that matches the bool.
/// (true => pos_branch, false => neg_branch)
InlineBranch(bool),
/// Updates the specified branch with the new node
UpdateBranch { branch: bool, new_node: Node },
/// Updates the condition of a branch
UpdateBranchCondition(Condition),
/// Inlines the function of this function call.
InlineFunction,
/// Removes all aliases to a function which only redirects to another function
/// The argument specifies the aliased function.
RemoveAliasFunction(BlockId),
/// Changes the variable this node writes to
ChangeWrite(ItemId),
/// Replaces all variables `.0` with `.1`
ChangeReads(ItemId, ScoreboardValue),
/// Changes the condition of this branch to a new condition
/// Vec usize contains the exact index of the condition to replace
/// (Vec since conditions can be nested)
SetCondition(Condition, Vec<usize>),
/// Replaces the old node completely
Replace(Node),
/// Inserts this node after
InsertAfter(Node),
/// Modifies a [`Node::Execute`]
/// IMPORTANT: Right now the indices don't get normalized after a component is deleted
/// This means that this command should not get used anywhere else other than in the one branch in redundancy_optimizer
UpdateExecuteRaw(usize, ExecuteRawUpdate),
}
#[derive(Debug)]
pub enum ExecuteRawUpdate {
Delete,
Replace(Node),
}
#[derive(Debug)]
pub struct OptimizeCommand {
pub id: NodeId,
pub kind: OptimizeCommandKind,
}
impl OptimizeCommand {
pub fn new(id: NodeId, kind: OptimizeCommandKind) -> Self {
OptimizeCommand { id, kind }
}
/// Shifts the node id of this command one back
#[allow(clippy::cast_sign_loss)]
pub fn shift(&mut self, amt: i8) {
match amt.cmp(&0) {
Ordering::Greater => self.id.1 += amt as usize,
Ordering::Less => self.id.1 -= amt.unsigned_abs() as usize,
Ordering::Equal => {}
}
}
pub fn shift_back(&mut self) {
self.shift(-1);
}
pub fn shift_forward(&mut self) {
self.shift(1);
}
}
/// Just a wrapper around deque with a simple push method
#[derive(Debug)]
pub struct OptimizeCommandDeque<T>(VecDeque<T>);
impl<T> OptimizeCommandDeque<T> {
pub fn push(&mut self, value: T) {
self.0.push_back(value);
}
}
impl<T> Deref for OptimizeCommandDeque<T> {
type Target = VecDeque<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for OptimizeCommandDeque<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> Default for OptimizeCommandDeque<T> {
fn default() -> Self {
OptimizeCommandDeque(VecDeque::default())
}
}