NOT operator and UnaryOperator DCE

main
Shad Amethyst 1 year ago
parent 96fe0484f8
commit f9397f8cac

@ -243,13 +243,25 @@ The "return stack" is cleared at the beginning of the generated program.
`mlog` provides several ways for processors to interact with the in-game world, which are reflected in MinBasic using functions: `mlog` provides several ways for processors to interact with the in-game world, which are reflected in MinBasic using functions:
<!-- ### `sensor` ### Sensor, Control and Set Prop
The `sensor` instruction becomes the `.` operator: The easiest way to read data from units or blocks, and to write data to those, is to use the dot (`.`) operator:
```basic ```basic
health = SENSOR(@unit, @health) REM A simple program to shut down reactors when their health of cryofluid amount dips too low
health = @unit.health LET reactor = reactor1
@unit.health = @unit.health - 10 LET enoughHealth = reactor.health >= reactor.maxHealth / 2
``` --> LET enoughCryofluid = reactor.cryofluid >= reactor.liquidCapacity
IF NOT(enoughHealth AND enoughCryofluid) THEN
reactor.enabled = false
ELSE
reactor.enabled = true
END IF
```
When reading, the dot operator translates to the `sensor` instruction, and replaces the key with its corresponding `@`-variable (`block1.health` becomes `sensor @health block1`, `@unit.x` becomes `sensor @x @unit`, etc.)
When writing, the `control` instruction is used when possible, namely with `.enabled`, `.config` and `.color`.
Otherwise, the `setprop` instruction is used, which is only available to world processors, and the key is replaced with its corresponding `@`-variable.

@ -0,0 +1,11 @@
REM A simple program to shut down reactors when their health of cryofluid amount dips too low
LET reactor = reactor1
LET enoughHealth = reactor.health >= reactor.maxHealth / 2
LET enoughCryofluid = reactor.cryofluid >= reactor.liquidCapacity
IF NOT(enoughHealth AND enoughCryofluid) THEN
reactor.enabled = false
ELSE
reactor.enabled = true
END IF

@ -31,7 +31,9 @@ pub(crate) fn optimize_dead_code(program: MindustryProgram) -> MindustryProgram
replace_if( replace_if(
program, program,
|_instructions, instruction, _index| match instruction { |_instructions, instruction, _index| match instruction {
MindustryOperation::Set(name, _) | MindustryOperation::Operator(name, _, _, _) => { MindustryOperation::Set(name, _)
| MindustryOperation::Operator(name, _, _, _)
| MindustryOperation::UnaryOperator(name, _, _) => {
if !is_temporary_variable(name) { if !is_temporary_variable(name) {
return None; return None;
} }

@ -48,6 +48,11 @@ pub fn optimize_jump_op(program: MindustryProgram) -> MindustryProgram {
{ {
Lookaround::Stop((*operator, lhs.clone(), rhs.clone())) Lookaround::Stop((*operator, lhs.clone(), rhs.clone()))
} }
MindustryOperation::UnaryOperator(name, operator, value)
if *name == var_name && *operator == UnaryOperator::Not =>
{
Lookaround::Stop((Operator::Eq, value.clone(), Operand::Integer(0)))
}
x if x.mutates(&var_name) || x.breaks_flow() => Lookaround::Abort, x if x.mutates(&var_name) || x.breaks_flow() => Lookaround::Abort,
_ => Lookaround::Continue, _ => Lookaround::Continue,
}, },

@ -108,7 +108,7 @@ pub enum UnaryOperator {
Ceil, Ceil,
Rand, Rand,
Sqrt, Sqrt,
// Not, Not,
} }
impl TryFrom<&str> for UnaryOperator { impl TryFrom<&str> for UnaryOperator {
@ -121,17 +121,8 @@ impl TryFrom<&str> for UnaryOperator {
"ceil" => Ok(Self::Ceil), "ceil" => Ok(Self::Ceil),
"rand" => Ok(Self::Rand), "rand" => Ok(Self::Rand),
"sqrt" => Ok(Self::Sqrt), "sqrt" => Ok(Self::Sqrt),
"not" => Ok(Self::Not),
_ => Err(()), _ => Err(()),
} }
} }
} }
pub(crate) fn format_unary_operator(operator: UnaryOperator) -> &'static str {
match operator {
UnaryOperator::Floor => "floor",
UnaryOperator::Round => "round",
UnaryOperator::Ceil => "ceil",
UnaryOperator::Rand => "rand",
UnaryOperator::Sqrt => "sqrt",
}
}

@ -148,6 +148,18 @@ impl std::fmt::Display for MindustryProgram {
} }
} }
fn format_unary_operator(operator: UnaryOperator) -> &'static str {
match operator {
UnaryOperator::Floor => "floor",
UnaryOperator::Round => "round",
UnaryOperator::Ceil => "ceil",
UnaryOperator::Rand => "rand",
UnaryOperator::Sqrt => "sqrt",
// Note: we use `equal x 0` to implement the binary NOT operation
UnaryOperator::Not => "equal",
}
}
fn format_condition(operator: Operator) -> &'static str { fn format_condition(operator: Operator) -> &'static str {
match operator { match operator {
Operator::Eq => "equal", Operator::Eq => "equal",

Loading…
Cancel
Save