diff --git a/src/main/java/com/sk89q/worldedit/expression/runtime/Break.java b/src/main/java/com/sk89q/worldedit/expression/runtime/Break.java index 3a01fa4b3..b35303850 100644 --- a/src/main/java/com/sk89q/worldedit/expression/runtime/Break.java +++ b/src/main/java/com/sk89q/worldedit/expression/runtime/Break.java @@ -47,6 +47,4 @@ public class Break extends Node { public String toString() { return doContinue ? "continue" : "break"; } - - //TODO: optimizer } diff --git a/src/main/java/com/sk89q/worldedit/expression/runtime/Conditional.java b/src/main/java/com/sk89q/worldedit/expression/runtime/Conditional.java index c6c7d1c7c..06495a67f 100644 --- a/src/main/java/com/sk89q/worldedit/expression/runtime/Conditional.java +++ b/src/main/java/com/sk89q/worldedit/expression/runtime/Conditional.java @@ -42,7 +42,7 @@ public class Conditional extends Node { if (condition.getValue() > 0.0) { return truePart.getValue(); } else { - return falsePart == null ? 0 : falsePart.getValue(); + return falsePart == null ? 0.0 : falsePart.getValue(); } } @@ -62,5 +62,18 @@ public class Conditional extends Node { } } - //TODO: optimizer + @Override + public RValue optimize() throws EvaluationException { + final RValue newCondition = condition.optimize(); + + if (newCondition instanceof Constant) { + if (newCondition.getValue() > 0) { + return truePart.optimize(); + } else { + return falsePart == null ? new Constant(getPosition(), 0.0) : falsePart.optimize(); + } + } + + return new Conditional(getPosition(), newCondition, truePart.optimize(), falsePart.optimize()); + } } diff --git a/src/main/java/com/sk89q/worldedit/expression/runtime/For.java b/src/main/java/com/sk89q/worldedit/expression/runtime/For.java index 515fb2812..b3c397c34 100644 --- a/src/main/java/com/sk89q/worldedit/expression/runtime/For.java +++ b/src/main/java/com/sk89q/worldedit/expression/runtime/For.java @@ -74,5 +74,17 @@ public class For extends Node { return "for (" + init + "; " + condition + "; " + increment + ") { " + body + " }"; } - //TODO: optimizer + @Override + public RValue optimize() throws EvaluationException { + final RValue newCondition = condition.optimize(); + + if (newCondition instanceof Constant && newCondition.getValue() <= 0) { + // If the condition is always false, the loop can be flattened. + // So we run the init part and then return 0.0. + return new Sequence(getPosition(), init, new Constant(getPosition(), 0.0)).optimize(); + } + + //return new Sequence(getPosition(), init.optimize(), new While(getPosition(), condition, new Sequence(getPosition(), body, increment), false)).optimize(); + return new For(getPosition(), init.optimize(), newCondition, increment.optimize(), body.optimize()); + } } diff --git a/src/main/java/com/sk89q/worldedit/expression/runtime/Return.java b/src/main/java/com/sk89q/worldedit/expression/runtime/Return.java index 30e97845d..c9905eb63 100644 --- a/src/main/java/com/sk89q/worldedit/expression/runtime/Return.java +++ b/src/main/java/com/sk89q/worldedit/expression/runtime/Return.java @@ -47,6 +47,4 @@ public class Return extends Node { public String toString() { return "return " + value; } - - //TODO: optimizer } diff --git a/src/main/java/com/sk89q/worldedit/expression/runtime/Sequence.java b/src/main/java/com/sk89q/worldedit/expression/runtime/Sequence.java index 8da1db87d..bdf9615b8 100644 --- a/src/main/java/com/sk89q/worldedit/expression/runtime/Sequence.java +++ b/src/main/java/com/sk89q/worldedit/expression/runtime/Sequence.java @@ -88,6 +88,10 @@ public class Sequence extends Node { newSequence.add(droppedLast); } + if (newSequence.size() == 1) { + return newSequence.get(0); + } + return new Sequence(getPosition(), newSequence.toArray(new RValue[newSequence.size()])); } } diff --git a/src/main/java/com/sk89q/worldedit/expression/runtime/SimpleFor.java b/src/main/java/com/sk89q/worldedit/expression/runtime/SimpleFor.java index 44c43e775..2016873b6 100644 --- a/src/main/java/com/sk89q/worldedit/expression/runtime/SimpleFor.java +++ b/src/main/java/com/sk89q/worldedit/expression/runtime/SimpleFor.java @@ -78,5 +78,10 @@ public class SimpleFor extends Node { return "for (" + counter + " = " + first + ", " + last + ") { " + body + " }"; } - //TODO: optimizer + @Override + public RValue optimize() throws EvaluationException { + // TODO: unroll small loops into Sequences + + return new SimpleFor(getPosition(), (LValue) counter.optimize(), first.optimize(), last.optimize(), body.optimize()); + } } diff --git a/src/main/java/com/sk89q/worldedit/expression/runtime/While.java b/src/main/java/com/sk89q/worldedit/expression/runtime/While.java index 3f6e86200..6659502c4 100644 --- a/src/main/java/com/sk89q/worldedit/expression/runtime/While.java +++ b/src/main/java/com/sk89q/worldedit/expression/runtime/While.java @@ -95,5 +95,21 @@ public class While extends Node { } } - //TODO: optimizer + @Override + public RValue optimize() throws EvaluationException { + final RValue newCondition = condition.optimize(); + + if (newCondition instanceof Constant && newCondition.getValue() <= 0) { + // If the condition is always false, the loop can be flattened. + if (footChecked) { + // Foot-checked loops run at least once. + return body.optimize(); + } else { + // Loops that never run always return 0.0. + return new Constant(getPosition(), 0.0); + } + } + + return new While(getPosition(), newCondition, body.optimize(), footChecked); + } }