diff --git a/Cargo.lock b/Cargo.lock index 6a4d036..5f0b185 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -806,8 +806,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "workshop-rs" -version = "0.1.0" -source = "git+https://github.com/wrightkit/workshop-rs.git?rev=7b0f8c38b9d1ee627565e8406de25293df9b4f7f#7b0f8c38b9d1ee627565e8406de25293df9b4f7f" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad536c30d7c4765f71b6def933d06b10cb8aa8f6668da7196cda4c3fefcf5ca" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 33dd76e..8af78fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,10 +12,9 @@ repository = "https://github.com/wrightkit/wright" [workspace.dependencies] # Canonical Workshop core (wright#143): workshop-rs owns the Workshop catalog, # parser, emitter, detection, validation, and Workshop IR. This is the single -# pinned reference for the cutover — workspace crates consume it via -# `workshop-rs.workspace = true`. The rev is pinned to the accepted workshop-rs -# v0.2 candidate; do not consume workshop-rs main headless. -workshop-rs = { git = "https://github.com/wrightkit/workshop-rs.git", rev = "7b0f8c38b9d1ee627565e8406de25293df9b4f7f" } +# released reference for the cutover — workspace crates consume it via +# `workshop-rs.workspace = true`. +workshop-rs = "=0.1.1" [workspace.lints.rust] # Unsafe operations inside an unsafe function still need an explicit block so diff --git a/crates/wright-analyzer/src/service.rs b/crates/wright-analyzer/src/service.rs index 8176a7b..cbaf01e 100644 --- a/crates/wright-analyzer/src/service.rs +++ b/crates/wright-analyzer/src/service.rs @@ -219,6 +219,8 @@ impl<'a> SemanticService<'a> { let event = match &rule_data.event { wir::Event::Global => "global".to_string(), wir::Event::EachPlayer => "eachPlayer".to_string(), + wir::Event::EachPlayerWithFilters { .. } => "eachPlayer".to_string(), + wir::Event::Player { kind, .. } => kind.catalog_id().to_string(), wir::Event::Subroutine(subroutine) => { let name = self .program diff --git a/crates/wright-opy/src/reconstruct.rs b/crates/wright-opy/src/reconstruct.rs index ab25d5f..0cbcee4 100644 --- a/crates/wright-opy/src/reconstruct.rs +++ b/crates/wright-opy/src/reconstruct.rs @@ -630,6 +630,18 @@ impl<'a> Emitter<'a> { match &rule.event { Event::Global => self.out.push_str(" @Event global\n"), Event::EachPlayer => self.out.push_str(" @Event eachPlayer\n"), + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + } => self.out.push_str(" @Event eachPlayer\n"), + Event::EachPlayerWithFilters { .. } | Event::Player { .. } => { + self.issue( + "unsupported-rule-event", + format!("rule '{}' uses an event outside the OPY surface", rule.name), + rule.span, + ); + continue; + } Event::Subroutine(_) => { self.issue( "unsupported-rule-order", diff --git a/crates/wright-ostw/src/reconstruct.rs b/crates/wright-ostw/src/reconstruct.rs index 4d1b459..8845c2f 100644 --- a/crates/wright-ostw/src/reconstruct.rs +++ b/crates/wright-ostw/src/reconstruct.rs @@ -882,6 +882,15 @@ impl<'a> Emitter<'a> { Event::EachPlayer => { write!(header, " Event.OngoingPlayer").unwrap(); } + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + } => { + write!(header, " Event.OngoingPlayer").unwrap(); + } + Event::EachPlayerWithFilters { .. } | Event::Player { .. } => { + unreachable!("filtered/player events are outside the OSTW reconstruction surface") + } Event::Subroutine(_) => unreachable!("subroutine rules emit as functions"), } for condition in &rule.conditions { diff --git a/crates/wright-ostw/tests/differential.rs b/crates/wright-ostw/tests/differential.rs index c7b8e99..432ecc1 100644 --- a/crates/wright-ostw/tests/differential.rs +++ b/crates/wright-ostw/tests/differential.rs @@ -570,7 +570,38 @@ fn compare(actual: &wir::Program, expected: &wir::Program) -> Result<(), String> )); } match (&rule_a.event, &rule_b.event) { - (Event::Global, Event::Global) | (Event::EachPlayer, Event::EachPlayer) => {} + (Event::Global, Event::Global) + | (Event::EachPlayer, Event::EachPlayer) + | ( + Event::EachPlayer, + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + ) + | ( + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + Event::EachPlayer, + ) + | ( + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + ) => {} + (Event::EachPlayerWithFilters { .. }, _) + | (Event::Player { .. }, _) + | (_, Event::EachPlayerWithFilters { .. }) + | (_, Event::Player { .. }) => { + return Err(format!("rule {index} uses an unsupported event")); + } (Event::Subroutine(a), Event::Subroutine(b)) => { let name_a = actual .subroutines diff --git a/crates/wright-ostw/tests/reconstruct.rs b/crates/wright-ostw/tests/reconstruct.rs index 90e1833..006e815 100644 --- a/crates/wright-ostw/tests/reconstruct.rs +++ b/crates/wright-ostw/tests/reconstruct.rs @@ -495,7 +495,38 @@ fn compare(actual: &wir::Program, expected: &wir::Program) -> Result<(), String> )); } match (&rule_a.event, &rule_b.event) { - (Event::Global, Event::Global) | (Event::EachPlayer, Event::EachPlayer) => {} + (Event::Global, Event::Global) + | (Event::EachPlayer, Event::EachPlayer) + | ( + Event::EachPlayer, + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + ) + | ( + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + Event::EachPlayer, + ) + | ( + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + Event::EachPlayerWithFilters { + team: workshop_rs::wir::EventTeam::All, + target: workshop_rs::wir::EventTarget::All, + }, + ) => {} + (Event::EachPlayerWithFilters { .. }, _) + | (Event::Player { .. }, _) + | (_, Event::EachPlayerWithFilters { .. }) + | (_, Event::Player { .. }) => { + return Err(format!("rule {index} uses an unsupported event")); + } (Event::Subroutine(a), Event::Subroutine(b)) => { let name_a = actual .subroutines diff --git a/crates/wright-workshop/tests/parser.rs b/crates/wright-workshop/tests/parser.rs index 406c82e..0db93ca 100644 --- a/crates/wright-workshop/tests/parser.rs +++ b/crates/wright-workshop/tests/parser.rs @@ -146,7 +146,10 @@ fn parsed_events_are_canonical() { .iter() .map(|rule| match &rule.event { wir::Event::Global => "global".to_string(), - wir::Event::EachPlayer => "eachPlayer".to_string(), + wir::Event::EachPlayer | wir::Event::EachPlayerWithFilters { .. } => { + "eachPlayer".to_string() + } + wir::Event::Player { kind, .. } => kind.catalog_id().to_string(), wir::Event::Subroutine(subroutine) => format!( "subroutine:{}", program.subroutines.get(*subroutine).unwrap().name @@ -391,6 +394,14 @@ fn cross_domain_member_spelling_collisions_are_the_documented_inventory() { assert_eq!( collisions, vec![ + ( + "All".to_string(), + vec![ + "EventTeam".to_string(), + "EventPlayer".to_string(), + "Invis".to_string() + ] + ), ( "None".to_string(), vec![ @@ -401,11 +412,19 @@ fn cross_domain_member_spelling_collisions_are_the_documented_inventory() { ), ( "Team 1".to_string(), - vec!["Color".to_string(), "Team".to_string()] + vec![ + "Color".to_string(), + "Team".to_string(), + "EventTeam".to_string() + ] ), ( "Team 2".to_string(), - vec!["Color".to_string(), "Team".to_string()] + vec![ + "Color".to_string(), + "Team".to_string(), + "EventTeam".to_string() + ] ), ( "Up".to_string(),