From 133c24b059e3a67efc8cace488be30d5b2e5c8f5 Mon Sep 17 00:00:00 2001 From: Teakowa Date: Thu, 29 Oct 2026 20:51:41 +0800 Subject: [PATCH 1/2] fix(compiler): preserve zero literal slot precedence over capture replacement Keep zero literals in parameter slots that the size optimizer rewrites to False or Null, before applying a configured zero replacement. Reuse the existing literal-slot policy so arr.index(0) matches pinned OverPy 9.7.17 under optimizeForSize and replace0ByCapturePercentage. Add a canonical differential fixture covering index calls, nested calls, Null and False slots, directive fallback, and directive-only behavior. Fixes #670 --- .../src/compiler/lowering/action_calls.rs | 11 +++++- .../opy-rs/src/compiler/size_optimization.rs | 2 +- .../size_optimization/literal_slots.rs | 4 +-- .../compiler/tests/structural_convergence.rs | 5 +++ .../fixture.json | 23 +++++++++++++ .../structural-size-capture-slots/oracle.json | 34 +++++++++++++++++++ .../structural-size-capture-slots/source.opy | 17 ++++++++++ 7 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/fixture.json create mode 100644 crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json create mode 100644 crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy diff --git a/crates/opy-rs/src/compiler/lowering/action_calls.rs b/crates/opy-rs/src/compiler/lowering/action_calls.rs index 93d00bd3..f3d9e841 100644 --- a/crates/opy-rs/src/compiler/lowering/action_calls.rs +++ b/crates/opy-rs/src/compiler/lowering/action_calls.rs @@ -1,6 +1,7 @@ use super::*; use super::super::blizzard_global; +use super::super::size_optimization::{Slot, slot}; fn is_cased_color_tag(text: &[char], index: usize) -> Option { let remaining = text[index..].iter().collect::(); @@ -608,7 +609,15 @@ impl<'a> Lowering<'a> { // Team.1) but never the argument-only ones (0, the empty string). let operands = rule_condition_root && matches!(call_id, "==" | "!=" | "<" | "<=" | ">" | ">="); - for value in args { + for (index, value) in args.iter_mut().enumerate() { + if matches!(self.value(*value), Value::Number(0.0)) + && matches!( + slot(call_id, index), + Some(Slot::Boolean | Slot::FalseOnly | Slot::ZeroAsNull) + ) + { + continue; + } *value = self.apply_replacement(*value, call_id, span, operands); } } diff --git a/crates/opy-rs/src/compiler/size_optimization.rs b/crates/opy-rs/src/compiler/size_optimization.rs index 8fcd74e3..e78db77a 100644 --- a/crates/opy-rs/src/compiler/size_optimization.rs +++ b/crates/opy-rs/src/compiler/size_optimization.rs @@ -1,7 +1,7 @@ use workshop_rs::catalog::{Kind, ParamCoercions}; use workshop_rs::{Action, ModifyOp, Value}; -use self::literal_slots::{Slot, slot}; +pub(super) use self::literal_slots::{Slot, slot}; use super::Compiler; use super::lowering::{EMPTY_STRING_NAME, Lowering}; use super::operator_optimization::{falsy, literal_text, number_components}; diff --git a/crates/opy-rs/src/compiler/size_optimization/literal_slots.rs b/crates/opy-rs/src/compiler/size_optimization/literal_slots.rs index b8487ffb..5ce2875c 100644 --- a/crates/opy-rs/src/compiler/size_optimization/literal_slots.rs +++ b/crates/opy-rs/src/compiler/size_optimization/literal_slots.rs @@ -1,5 +1,5 @@ #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(super) enum Slot { +pub(in crate::compiler) enum Slot { Boolean, TrueOnly, FalseOnly, @@ -7,7 +7,7 @@ pub(super) enum Slot { ZeroVectorAsNull, } -pub(super) fn slot(name: &str, index: usize) -> Option { +pub(in crate::compiler) fn slot(name: &str, index: usize) -> Option { Some(match (name, index) { ("startForcingSpawn", 1) => Slot::FalseOnly, ("add", 0 | 1) | ("divide", 0) | ("modulo", 0 | 1) | ("subtract", 1) => Slot::TrueOnly, diff --git a/crates/opy-rs/src/compiler/tests/structural_convergence.rs b/crates/opy-rs/src/compiler/tests/structural_convergence.rs index 8fb3b038..fe18a7f9 100644 --- a/crates/opy-rs/src/compiler/tests/structural_convergence.rs +++ b/crates/opy-rs/src/compiler/tests/structural_convergence.rs @@ -179,6 +179,11 @@ fn size_optimization_action_values_match_the_pinned_oracle() { assert_converges("structural-size-action-values"); } +#[test] +fn literal_slots_take_precedence_over_the_capture_replacement() { + assert_converges("structural-size-capture-slots"); +} + #[test] fn condition_operands_skip_the_argument_replacements() { assert_converges("structural-size-condition-replacements"); diff --git a/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/fixture.json b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/fixture.json new file mode 100644 index 00000000..2118d0aa --- /dev/null +++ b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/fixture.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 1, + "id": "synthetic/structural-size-capture-slots", + "category": "compiler", + "features": [ + "optimizeForSize", + "preprocessing/replacements" + ], + "source": "source.opy", + "tests": { + "source": { + "nativeStatus": "success", + "relationship": "match", + "ruleNames": true + }, + "compiler": { + "nativeStatus": "success", + "relationship": "match", + "comparison": "semantic-wir", + "semanticEquivalent": true + } + } +} diff --git a/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json new file mode 100644 index 00000000..abee6a02 --- /dev/null +++ b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json @@ -0,0 +1,34 @@ +{ + "compile": { + "diagnostics": [], + "exitCode": 0, + "status": "success", + "stdout": "", + "workshop": "variables {\n global:\n 0: arr\n 1: result\n}\n\nrule (\"capture directive without size optimization\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, 0));\n }\n}\n\n//Optimize for size enabled\nrule (\"literal slots precede capture replacement\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, 1));\n Set Global Variable(result, Array Contains(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Index Of Array Value(Global.arr, Null)));\n Wait(False, Ignore Condition);\n Create HUD Text(All Players(All Teams), Point Capture Percentage, Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003{0}\", Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\")), Null, Left, -9999, Color(Orange), Null, Null, Visible To and String, Default Visibility);\n }\n}\n", + "workshopExact": "variables {\n global:\n 0: arr\n 1: result\n}\n\nrule (\"capture directive without size optimization\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, 0));\n }\n}\n\n//Optimize for size enabled\nrule (\"literal slots precede capture replacement\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, 1));\n Set Global Variable(result, Array Contains(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Index Of Array Value(Global.arr, Null)));\n Wait(False, Ignore Condition);\n Create HUD Text(All Players(All Teams), Point Capture Percentage, Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003{0}\", Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\")), Null, Left, -9999, Color(Orange), Null, Null, Visible To and String, Default Visibility);\n }\n}\n\n", + "workshopSha256": "06f223fccbc71e1080ef6a0e759c25a5abaf72775e370d7361a7c34a96362954" + }, + "fixture": "synthetic/structural-size-capture-slots", + "input": { + "files": [ + { + "path": "source.opy", + "sha256": "7f129bb013abee4e29b02c5636f150d995894e0d888799f9e00afa88730b6dac" + } + ], + "sha256": "328bbb67ec8a57ed6699035dcedda66f07f578bd9781f96d88da80f64ad41016", + "source": "source.opy" + }, + "oracle": { + "contentCommit": "5a7d0e294b8cad73b9701987bb584d0551d7fa4d", + "gitHead": "ec763c1d245aa5485ef61af5b2bda4975bce4877", + "integrity": "sha512-C5F6btT5yn19BvHuE0bjMuSd/2esebBabmpL4SYLQFuJ4IdouVOKEoMLLuJFAyNc0Phwrolblj5GDkDGYR0ofg==", + "language": "en-US", + "license": "GPL-3.0-only", + "name": "overpy", + "registryTarball": "https://registry.npmjs.org/overpy/-/overpy-9.7.17.tgz", + "repository": "https://github.com/Zezombye/overpy", + "version": "9.7.17" + }, + "schemaVersion": 1 +} diff --git a/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy new file mode 100644 index 00000000..f11924b3 --- /dev/null +++ b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy @@ -0,0 +1,17 @@ +#!replace0ByCapturePercentage +globalvar arr +globalvar result + +rule "capture directive without size optimization": + @Event global + result = arr.index(0) + +#!optimizeForSize +rule "literal slots precede capture replacement": + @Event global + result = arr.index(0) + result = arr.index(1) + result = 0 in arr + result = arr.index(arr.index(0)) + wait(0) + print(0) From 61c48896b212e673972d9524d738f3ace1bda394 Mon Sep 17 00:00:00 2001 From: Teakowa Date: Thu, 29 Oct 2026 21:39:36 +0800 Subject: [PATCH 2/2] fix(compiler): preserve replacement precedence in modify and comparison operands Restore directive replacement for zero operands consumed by max/min self-assignment rewrites, while retaining False for surviving value calls. Preserve comparison zero operands for the existing Null size rewrite. Extend the canonical differential fixture with the four review reproducers and directive-only, disabled-optimization, and rule-condition controls. Refs #670 --- .../src/compiler/lowering/action_calls.rs | 9 ++++---- .../opy-rs/src/compiler/size_optimization.rs | 13 +++++++++++ .../structural-size-capture-slots/oracle.json | 10 ++++---- .../structural-size-capture-slots/source.opy | 23 +++++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/crates/opy-rs/src/compiler/lowering/action_calls.rs b/crates/opy-rs/src/compiler/lowering/action_calls.rs index f3d9e841..f0bf7fa7 100644 --- a/crates/opy-rs/src/compiler/lowering/action_calls.rs +++ b/crates/opy-rs/src/compiler/lowering/action_calls.rs @@ -611,10 +611,11 @@ impl<'a> Lowering<'a> { rule_condition_root && matches!(call_id, "==" | "!=" | "<" | "<=" | ">" | ">="); for (index, value) in args.iter_mut().enumerate() { if matches!(self.value(*value), Value::Number(0.0)) - && matches!( - slot(call_id, index), - Some(Slot::Boolean | Slot::FalseOnly | Slot::ZeroAsNull) - ) + && (matches!(call_id, "==" | "!=" | "<" | "<=" | ">" | ">=") + || matches!( + slot(call_id, index), + Some(Slot::Boolean | Slot::FalseOnly | Slot::ZeroAsNull) + )) { continue; } diff --git a/crates/opy-rs/src/compiler/size_optimization.rs b/crates/opy-rs/src/compiler/size_optimization.rs index e78db77a..fb7178cc 100644 --- a/crates/opy-rs/src/compiler/size_optimization.rs +++ b/crates/opy-rs/src/compiler/size_optimization.rs @@ -94,6 +94,19 @@ impl<'a> SizeOptimizer<'a> { } fn modified(&self, op: ModifyOp, value: &mut Value) { + if matches!(op, ModifyOp::Max | ModifyOp::Min) && matches!(value, Value::Number(0.0)) { + let replacement = [ + "getCapturePercentage", + "getPayloadProgressPercentage", + "isMatchComplete", + ] + .into_iter() + .find(|name| self.replacement(name)); + if let Some(name) = replacement { + *value = Value::call(name, []); + return; + } + } if is_empty_string(value) { *value = self.empty_string(false); return; diff --git a/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json index abee6a02..8463bc8c 100644 --- a/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json +++ b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/oracle.json @@ -4,19 +4,19 @@ "exitCode": 0, "status": "success", "stdout": "", - "workshop": "variables {\n global:\n 0: arr\n 1: result\n}\n\nrule (\"capture directive without size optimization\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, 0));\n }\n}\n\n//Optimize for size enabled\nrule (\"literal slots precede capture replacement\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, 1));\n Set Global Variable(result, Array Contains(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Index Of Array Value(Global.arr, Null)));\n Wait(False, Ignore Condition);\n Create HUD Text(All Players(All Teams), Point Capture Percentage, Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003{0}\", Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\")), Null, Left, -9999, Color(Orange), Null, Null, Visible To and String, Default Visibility);\n }\n}\n", - "workshopExact": "variables {\n global:\n 0: arr\n 1: result\n}\n\nrule (\"capture directive without size optimization\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, 0));\n }\n}\n\n//Optimize for size enabled\nrule (\"literal slots precede capture replacement\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, 1));\n Set Global Variable(result, Array Contains(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Index Of Array Value(Global.arr, Null)));\n Wait(False, Ignore Condition);\n Create HUD Text(All Players(All Teams), Point Capture Percentage, Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003{0}\", Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\")), Null, Left, -9999, Color(Orange), Null, Null, Visible To and String, Default Visibility);\n }\n}\n\n", - "workshopSha256": "06f223fccbc71e1080ef6a0e759c25a5abaf72775e370d7361a7c34a96362954" + "workshop": "variables {\n global:\n 0: arr\n 1: result\n}\n\nrule (\"capture directive without size optimization\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, 0));\n Modify Global Variable(result, Max, 0);\n Modify Global Variable(result, Min, 0);\n Set Global Variable(result, Compare(Global.result, ==, 0));\n Set Global Variable(result, Index Of Array Value(Global.arr, Compare(Global.result, ==, 0)));\n }\n}\n\n//Optimize for size enabled\nrule (\"literal slots precede capture replacement\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, 1));\n Set Global Variable(result, Array Contains(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Index Of Array Value(Global.arr, Null)));\n Wait(False, Ignore Condition);\n Create HUD Text(All Players(All Teams), Point Capture Percentage, Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003{0}\", Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\")), Null, Left, -9999, Color(Orange), Null, Null, Visible To and String, Default Visibility);\n Modify Global Variable(result, Max, Point Capture Percentage);\n Modify Global Variable(result, Min, Point Capture Percentage);\n Set Global Variable(result, Max(Global.arr, False));\n Set Global Variable(result, Min(Global.arr, False));\n Set Global Variable(result, Compare(Global.result, ==, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Compare(Global.result, ==, Null)));\n }\n}\n\nrule (\"capture comparison condition\") {\n event {\n Ongoing - Global;\n }\n conditions {\n Global.result == Null;\n }\n actions {\n Set Global Variable(result, 1);\n }\n}\n\n//Optimizations disabled\nrule (\"capture directive with optimizations disabled\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Max(Global.result, 0));\n Set Global Variable(result, Min(Global.result, 0));\n Set Global Variable(result, Compare(Global.result, ==, 0));\n Set Global Variable(result, Index Of Array Value(Global.arr, Compare(Global.result, ==, 0)));\n }\n}\n", + "workshopExact": "variables {\n global:\n 0: arr\n 1: result\n}\n\nrule (\"capture directive without size optimization\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, 0));\n Modify Global Variable(result, Max, 0);\n Modify Global Variable(result, Min, 0);\n Set Global Variable(result, Compare(Global.result, ==, 0));\n Set Global Variable(result, Index Of Array Value(Global.arr, Compare(Global.result, ==, 0)));\n }\n}\n\n//Optimize for size enabled\nrule (\"literal slots precede capture replacement\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Index Of Array Value(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, 1));\n Set Global Variable(result, Array Contains(Global.arr, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Index Of Array Value(Global.arr, Null)));\n Wait(False, Ignore Condition);\n Create HUD Text(All Players(All Teams), Point Capture Percentage, Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003{0}\", Custom String(\"\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\")), Null, Left, -9999, Color(Orange), Null, Null, Visible To and String, Default Visibility);\n Modify Global Variable(result, Max, Point Capture Percentage);\n Modify Global Variable(result, Min, Point Capture Percentage);\n Set Global Variable(result, Max(Global.arr, False));\n Set Global Variable(result, Min(Global.arr, False));\n Set Global Variable(result, Compare(Global.result, ==, Null));\n Set Global Variable(result, Index Of Array Value(Global.arr, Compare(Global.result, ==, Null)));\n }\n}\n\nrule (\"capture comparison condition\") {\n event {\n Ongoing - Global;\n }\n conditions {\n Global.result == Null;\n }\n actions {\n Set Global Variable(result, 1);\n }\n}\n\n//Optimizations disabled\nrule (\"capture directive with optimizations disabled\") {\n event {\n Ongoing - Global;\n }\n actions {\n Set Global Variable(result, Max(Global.result, 0));\n Set Global Variable(result, Min(Global.result, 0));\n Set Global Variable(result, Compare(Global.result, ==, 0));\n Set Global Variable(result, Index Of Array Value(Global.arr, Compare(Global.result, ==, 0)));\n }\n}\n\n", + "workshopSha256": "e4a7ed467e5831ca205d30cac2d2e2227fd36b8c119fa6cd938338b829eea815" }, "fixture": "synthetic/structural-size-capture-slots", "input": { "files": [ { "path": "source.opy", - "sha256": "7f129bb013abee4e29b02c5636f150d995894e0d888799f9e00afa88730b6dac" + "sha256": "b87390e38852bf1268adb1ba414a988046810705d69ddd8e6b2a62b710d0e1b2" } ], - "sha256": "328bbb67ec8a57ed6699035dcedda66f07f578bd9781f96d88da80f64ad41016", + "sha256": "3a9dcb53aa184fe9d0ec387e6b32dcd237a638a3acfb75e54ca28020c5ff6659", "source": "source.opy" }, "oracle": { diff --git a/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy index f11924b3..e182ef72 100644 --- a/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy +++ b/crates/opy-rs/tests/fixtures/corpus/synthetic/structural-size-capture-slots/source.opy @@ -5,6 +5,10 @@ globalvar result rule "capture directive without size optimization": @Event global result = arr.index(0) + result = max(result, 0) + result = min(result, 0) + result = (result == 0) + result = arr.index(result == 0) #!optimizeForSize rule "literal slots precede capture replacement": @@ -15,3 +19,22 @@ rule "literal slots precede capture replacement": result = arr.index(arr.index(0)) wait(0) print(0) + result = max(result, 0) + result = min(result, 0) + result = max(arr, 0) + result = min(arr, 0) + result = (result == 0) + result = arr.index(result == 0) + +rule "capture comparison condition": + @Event global + @Condition result == 0 + result = 1 + +#!disableOptimizations +rule "capture directive with optimizations disabled": + @Event global + result = max(result, 0) + result = min(result, 0) + result = (result == 0) + result = arr.index(result == 0)