From 6f4b9139483b3166aba061ecfefc0360a24b92fe Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 06:45:28 -0700 Subject: [PATCH 01/11] Add available-locations to Projector --- chorus_lib/examples/bookseller.rs | 7 +-- chorus_lib/examples/bookseller2.rs | 18 ++++++-- chorus_lib/examples/hello.rs | 9 ++-- chorus_lib/examples/loc-poly.rs | 9 ++-- chorus_lib/examples/tic-tac-toe.rs | 10 +++-- chorus_lib/src/core.rs | 68 ++++++++++++++++++++++++------ 6 files changed, 93 insertions(+), 28 deletions(-) diff --git a/chorus_lib/examples/bookseller.rs b/chorus_lib/examples/bookseller.rs index 3b1bcfa..d55a2f2 100644 --- a/chorus_lib/examples/bookseller.rs +++ b/chorus_lib/examples/bookseller.rs @@ -6,7 +6,7 @@ use std::thread; use chorus_lib::hlist; use chrono::NaiveDate; -use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; +use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, ProjectorForAL}; use chorus_lib::transport::local::LocalTransport; fn get_book(title: &str) -> Option<(i32, NaiveDate)> { @@ -74,8 +74,9 @@ impl Choreography for BooksellerChoreography { fn main() { let transport = LocalTransport::from(&[Seller::name(), Buyer::name()]); - let seller_projector = Projector::new(Seller, transport.clone()); - let buyer_projector = Projector::new(Buyer, transport.clone()); + type AL = hlist!(Buyer, Seller); + let seller_projector = ProjectorForAL::::new(Seller, transport.clone()); + let buyer_projector = ProjectorForAL::::new(Buyer, transport.clone()); let mut handles: Vec> = Vec::new(); handles.push(thread::spawn(move || { diff --git a/chorus_lib/examples/bookseller2.rs b/chorus_lib/examples/bookseller2.rs index 437452c..badd67f 100644 --- a/chorus_lib/examples/bookseller2.rs +++ b/chorus_lib/examples/bookseller2.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap, sync::Arc}; use chorus_lib::hlist; use chorus_lib::{ - core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Projector}, + core::{ChoreoOp, Choreography, ChoreographyLocation, Located, ProjectorForAL}, transport::local::LocalTransport, }; use chrono::NaiveDate; @@ -142,10 +142,20 @@ fn main() { i }; + type AL = hlist!(Seller, Buyer1, Buyer2); let transport = LocalTransport::from(&[Seller::name(), Buyer1::name(), Buyer2::name()]); - let seller_projector = Arc::new(Projector::new(Seller, transport.clone())); - let buyer1_projector = Arc::new(Projector::new(Buyer1, transport.clone())); - let buyer2_projector = Arc::new(Projector::new(Buyer2, transport.clone())); + let seller_projector = Arc::new(ProjectorForAL::::new( + Seller, + transport.clone() + )); + let buyer1_projector = Arc::new(ProjectorForAL::::new( + Buyer1, + transport.clone(), + )); + let buyer2_projector = Arc::new(ProjectorForAL::::new( + Buyer2, + transport.clone(), + )); println!("Tries to buy HoTT with one buyer"); type OneBuyerBooksellerChoreography = BooksellerChoreography; diff --git a/chorus_lib/examples/hello.rs b/chorus_lib/examples/hello.rs index cbf0597..cb51867 100644 --- a/chorus_lib/examples/hello.rs +++ b/chorus_lib/examples/hello.rs @@ -2,7 +2,7 @@ extern crate chorus_lib; use std::thread; -use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; +use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, ProjectorForAL}; use chorus_lib::hlist; use chorus_lib::transport::local::LocalTransport; @@ -41,18 +41,21 @@ fn main() { let mut handles: Vec> = Vec::new(); // Create a local transport let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); + // Crate available locations for Projector + type AL = hlist!(Alice, Bob); + // Run the choreography in two threads { let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = Projector::new(Alice, transport); + let p = ProjectorForAL::::new(Alice, transport); p.epp_and_run(HelloWorldChoreography); })); } { let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = Projector::new(Bob, transport); + let p = ProjectorForAL::::new(Bob, transport); p.epp_and_run(HelloWorldChoreography); })); } diff --git a/chorus_lib/examples/loc-poly.rs b/chorus_lib/examples/loc-poly.rs index 7b46924..5b5613c 100644 --- a/chorus_lib/examples/loc-poly.rs +++ b/chorus_lib/examples/loc-poly.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use std::thread; use chorus_lib::core::{ - ChoreoOp, Choreography, ChoreographyLocation, Located, Portable, Projector, + ChoreoOp, Choreography, ChoreographyLocation, Located, Portable, ProjectorForAL, }; use chorus_lib::hlist; use chorus_lib::transport::local::LocalTransport; @@ -59,11 +59,14 @@ impl Choreography> for MainChoreography { fn main() { let transport = LocalTransport::from(&[Alice::name(), Bob::name(), Carol::name()]); + // Crate available locations for Projector + type AL = hlist!(Alice, Bob); + let mut handles = vec![]; { let transport = transport.clone(); handles.push(thread::spawn(|| { - let p = Projector::new(Alice, transport); + let p = ProjectorForAL::::new(Alice, transport); let v = p.epp_and_run(MainChoreography); assert_eq!(p.unwrap(v), 110); })); @@ -71,7 +74,7 @@ fn main() { { let transport = transport.clone(); handles.push(thread::spawn(|| { - let p = Projector::new(Bob, transport); + let p = ProjectorForAL::::new(Bob, transport); p.epp_and_run(MainChoreography); })); } diff --git a/chorus_lib/examples/tic-tac-toe.rs b/chorus_lib/examples/tic-tac-toe.rs index 456c643..5211518 100644 --- a/chorus_lib/examples/tic-tac-toe.rs +++ b/chorus_lib/examples/tic-tac-toe.rs @@ -3,7 +3,7 @@ extern crate chorus_lib; use chorus_lib::{ core::{ - ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, Projector, Serialize, + ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, ProjectorForAL, Serialize, }, hlist, transport::http::HttpTransport, @@ -290,6 +290,10 @@ fn main() { } else { Box::new(UserBrain::new(args.player)) }; + + // Crate available locations for Projector + type AL = hlist!(PlayerX, PlayerO); + match args.player { 'X' => { let mut config = HashMap::new(); @@ -299,7 +303,7 @@ fn main() { (args.opponent_hostname.as_str(), args.opponent_port), ); let transport = HttpTransport::new(PlayerX::name(), &config); - let projector = Projector::new(PlayerX, transport); + let projector = ProjectorForAL::::new(PlayerX, transport); projector.epp_and_run(TicTacToeChoreography { brain_for_x: projector.local(brain), brain_for_o: projector.remote(PlayerO), @@ -313,7 +317,7 @@ fn main() { (args.opponent_hostname.as_str(), args.opponent_port), ); let transport = HttpTransport::new(PlayerO::name(), &config); - let projector = Projector::new(PlayerO, transport); + let projector = ProjectorForAL::::new(PlayerO, transport); projector.epp_and_run(TicTacToeChoreography { brain_for_x: projector.remote(PlayerX), brain_for_o: projector.local(brain), diff --git a/chorus_lib/src/core.rs b/chorus_lib/src/core.rs index 972c639..f047cd0 100644 --- a/chorus_lib/src/core.rs +++ b/chorus_lib/src/core.rs @@ -168,6 +168,22 @@ where { } +/// Equal + pub trait Equal {} + + // Base case: HNil is equal to HNil + impl Equal for HNil {} + + // Recursive case: Head::Tail is equal to L if + // 1. Head is a member of L + // 2. Tail is equal to the remainder of L + impl Equal> for HCons + where + Head: Member, + Tail: Equal, + { + } + /// Provides a method to work with located values at the current location pub struct Unwrapper { phantom: PhantomData, @@ -271,28 +287,55 @@ pub trait Transport { } /// Provides a method to perform end-point projection. -pub struct Projector { +pub struct Projector where + L1: Member{ target: PhantomData, transport: T, + available_locations: PhantomData, + index: PhantomData, +} + +/// Provides a wrapper struct for users so that they can only specify AL; since it can't be inferred. +pub struct ProjectorForAL(PhantomData); + +impl ProjectorForAL { + /// Constructs a `Projector` struct. + /// + /// - `target` is the projection target of the choreography. + /// - `transport` is an implementation of `Transport`. + pub fn new( + target: L1, + transport: B, + ) -> Projector + where + L1: Member, + { + Projector::new(target, transport) + } } -impl Projector { +impl Projector + where L1: Member +{ /// Constructs a `Projector` struct. /// /// - `target` is the projection target of the choreography. /// - `transport` is an implementation of `Transport`. - pub fn new(target: L1, transport: B) -> Self { - let _ = target; + pub fn new(_target: L1, transport: B) -> Self + { Projector { target: PhantomData, transport, + available_locations: PhantomData, + index: PhantomData, } } /// Constructs a `Located` struct located at the projection target using the actual value. /// /// Use this method to run a choreography that takes a located value as an input. - pub fn local(&self, value: V) -> Located { + pub fn local(&self, value: V) -> Located + { Located::local(value) } @@ -301,12 +344,10 @@ impl Projector { /// Use this method to run a choreography that takes a located value as an input. /// /// Note that the method panics at runtime if the projection target and the location of the value are the same. - pub fn remote(&self, l2: L2) -> Located { - let _ = l2; - // NOTE(shumbo): Ideally, this check should be done at the type level. - if L1::name() == L2::name() { - panic!("Cannot create a remote value at the same location"); - } + pub fn remote(&self, _l2: L2) -> Located + where + L2: Member<>::Remainder, Index2>, + { Located::remote() } @@ -318,7 +359,10 @@ impl Projector { } /// Performs end-point projection and runs a choreography. - pub fn epp_and_run<'a, V, L: HList, C: Choreography>(&'a self, choreo: C) -> V { + pub fn epp_and_run<'a, V, L: HList, C: Choreography, IndexSet>(&'a self, choreo: C) -> V + where + L: Equal, + { struct EppOp<'a, L: HList, L1: ChoreographyLocation, B: Transport> { target: PhantomData, transport: &'a B, From 66fd8914eb9a5b6677eede900b3712f0e90d2d2b Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 07:00:13 -0700 Subject: [PATCH 02/11] Update the book to use available locations for Projector --- chorus_book/src/guide-input-and-output.md | 14 +++++++------- chorus_book/src/guide-projector.md | 12 +++++++----- chorus_book/src/guide-transport.md | 13 +++++++++---- chorus_book/src/header.txt | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/chorus_book/src/guide-input-and-output.md b/chorus_book/src/guide-input-and-output.md index 8ac7ca5..924ab98 100644 --- a/chorus_book/src/guide-input-and-output.md +++ b/chorus_book/src/guide-input-and-output.md @@ -33,7 +33,7 @@ You can construct an instance of the choreography with the input and pass it to # input: String, # } # impl Choreography for DemoChoreography { -# type L = hlist!(); +# type L = hlist!(Alice); # fn run(self, op: &impl ChoreoOp) { # println!("Input: {}", self.input); # } @@ -42,7 +42,7 @@ You can construct an instance of the choreography with the input and pass it to let choreo = DemoChoreography { input: "World".to_string(), }; -let projector = Projector::new(Alice, transport); +let projector = ProjectorForAL::::new(Alice, transport); projector.epp_and_run(choreo); ``` @@ -92,7 +92,7 @@ To run the sample choreography above at Alice, we use the `local` method to cons # }); # } # } -let projector_for_alice = Projector::new(Alice, transport); +let projector_for_alice = ProjectorForAL::::new(Alice, transport); // Because the target of the projector is Alice, the located value is available at Alice. let string_at_alice: Located = projector_for_alice.local("Hello, World!".to_string()); // Instantiate the choreography with the located value @@ -111,7 +111,7 @@ For Bob, we use the `remote` method to construct the located value. # } # # impl Choreography for DemoChoreography { -# type L = hlist!(Alice); +# type L = hlist!(Alice, Bob); # fn run(self, op: &impl ChoreoOp) { # op.locally(Alice, |un| { # let input = un.unwrap(&self.input); @@ -119,7 +119,7 @@ For Bob, we use the `remote` method to construct the located value. # }); # } # } -let projector_for_bob = Projector::new(Bob, transport); +let projector_for_bob = ProjectorForAL::::new(Bob, transport); // Construct a remote located value at Alice. The actual value is not required. let string_at_alice = projector_for_bob.remote(Alice); // Instantiate the choreography with the located value @@ -160,7 +160,7 @@ impl Choreography for DemoChoreography { # } # } let choreo = DemoChoreography; -let projector = Projector::new(Alice, transport); +let projector = ProjectorForAL::::new(Alice, transport); let output = projector.epp_and_run(choreo); assert_eq!(output, "Hello, World!".to_string()); ``` @@ -182,7 +182,7 @@ impl Choreography> for DemoChoreography { } } -let projector = Projector::new(Alice, transport); +let projector = ProjectorForAL::::new(Alice, transport); let output = projector.epp_and_run(DemoChoreography); let string_at_alice = projector.unwrap(output); assert_eq!(string_at_alice, "Hello, World!".to_string()); diff --git a/chorus_book/src/guide-projector.md b/chorus_book/src/guide-projector.md index 9e41bea..c56e632 100644 --- a/chorus_book/src/guide-projector.md +++ b/chorus_book/src/guide-projector.md @@ -9,14 +9,15 @@ To create a `Projector`, you need to provide the location and the transport. ```rust # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; -# use chorus_lib::core::{ChoreographyLocation, Projector}; +# use chorus_lib::core::{ChoreographyLocation, ProjectorForAL}; +# use chorus_lib::hlist; # let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); # #[derive(ChoreographyLocation)] # struct Alice; # #[derive(ChoreographyLocation)] # struct Bob; # -let projector = Projector::new(Alice, transport); +let projector = ProjectorForAL::::new(Alice, transport); ``` Notice that the `Projector` is parameterized by the location type. You will need one projector for each location to execute choreography. @@ -28,7 +29,8 @@ To execute a choreography, you need to call the `epp_and_run` method on the `Pro ```rust # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; -# use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp, HNil}; +# use chorus_lib::core::{ChoreographyLocation, ProjectorForAL, Choreography, ChoreoOp}; +# use chorus_lib::hlist; # let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); # #[derive(ChoreographyLocation)] # struct Alice; @@ -36,12 +38,12 @@ To execute a choreography, you need to call the `epp_and_run` method on the `Pro # struct Bob; # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = HNil; +# type L = hlist!(Alice); # fn run(self, op: &impl ChoreoOp) { # } # } # -# let projector = Projector::new(Alice, transport); +# let projector = ProjectorForAL::::new(Alice, transport); projector.epp_and_run(HelloWorldChoreography); ``` diff --git a/chorus_book/src/guide-transport.md b/chorus_book/src/guide-transport.md index a3ae384..01c7b90 100644 --- a/chorus_book/src/guide-transport.md +++ b/chorus_book/src/guide-transport.md @@ -25,24 +25,29 @@ Because of the nature of the `Local` transport, you must use the same `LocalTran # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; # use std::thread; -# use chorus_lib::core::{ChoreographyLocation, ChoreoOp, Choreography, Projector, HNil}; +# use chorus_lib::core::{ChoreographyLocation, ChoreoOp, Choreography, ProjectorForAL}; +# use chorus_lib::hlist; # #[derive(ChoreographyLocation)] # struct Alice; # #[derive(ChoreographyLocation)] # struct Bob; # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = HNil; +# type L = hlist!(Alice, Bob); # fn run(self, op: &impl ChoreoOp) { # } # } + +// Crate available locations for Projector +type AL = hlist!(Alice, Bob); + let mut handles: Vec> = Vec::new(); let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); { // create a clone for Alice let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = Projector::new(Alice, transport); + let p = ProjectorForAL::::new(Alice, transport); p.epp_and_run(HelloWorldChoreography); })); } @@ -50,7 +55,7 @@ let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); // create another for Bob let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = Projector::new(Bob, transport); + let p = ProjectorForAL::::new(Bob, transport); p.epp_and_run(HelloWorldChoreography); })); } diff --git a/chorus_book/src/header.txt b/chorus_book/src/header.txt index 3b12443..6c1f207 100644 --- a/chorus_book/src/header.txt +++ b/chorus_book/src/header.txt @@ -1,5 +1,5 @@ # extern crate chorus_lib; -# use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector, Located, Superposition, Runner}; +# use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, ProjectorForAL, Located, Superposition, Runner}; # use chorus_lib::transport::local::LocalTransport; # use chorus_lib::hlist; # #[derive(ChoreographyLocation)] From a2696b5dbe11bd4608fad6c28db6e06641fb110d Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 07:00:58 -0700 Subject: [PATCH 03/11] Format code --- chorus_lib/examples/bookseller.rs | 2 +- chorus_lib/examples/bookseller2.rs | 17 +++-------- chorus_lib/examples/tic-tac-toe.rs | 3 +- chorus_lib/src/core.rs | 46 ++++++++++++++++-------------- 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/chorus_lib/examples/bookseller.rs b/chorus_lib/examples/bookseller.rs index d55a2f2..16d1316 100644 --- a/chorus_lib/examples/bookseller.rs +++ b/chorus_lib/examples/bookseller.rs @@ -74,7 +74,7 @@ impl Choreography for BooksellerChoreography { fn main() { let transport = LocalTransport::from(&[Seller::name(), Buyer::name()]); - type AL = hlist!(Buyer, Seller); + type AL = hlist!(Buyer, Seller); let seller_projector = ProjectorForAL::::new(Seller, transport.clone()); let buyer_projector = ProjectorForAL::::new(Buyer, transport.clone()); diff --git a/chorus_lib/examples/bookseller2.rs b/chorus_lib/examples/bookseller2.rs index badd67f..c72e94d 100644 --- a/chorus_lib/examples/bookseller2.rs +++ b/chorus_lib/examples/bookseller2.rs @@ -142,20 +142,11 @@ fn main() { i }; - type AL = hlist!(Seller, Buyer1, Buyer2); + type AL = hlist!(Seller, Buyer1, Buyer2); let transport = LocalTransport::from(&[Seller::name(), Buyer1::name(), Buyer2::name()]); - let seller_projector = Arc::new(ProjectorForAL::::new( - Seller, - transport.clone() - )); - let buyer1_projector = Arc::new(ProjectorForAL::::new( - Buyer1, - transport.clone(), - )); - let buyer2_projector = Arc::new(ProjectorForAL::::new( - Buyer2, - transport.clone(), - )); + let seller_projector = Arc::new(ProjectorForAL::::new(Seller, transport.clone())); + let buyer1_projector = Arc::new(ProjectorForAL::::new(Buyer1, transport.clone())); + let buyer2_projector = Arc::new(ProjectorForAL::::new(Buyer2, transport.clone())); println!("Tries to buy HoTT with one buyer"); type OneBuyerBooksellerChoreography = BooksellerChoreography; diff --git a/chorus_lib/examples/tic-tac-toe.rs b/chorus_lib/examples/tic-tac-toe.rs index 5211518..d53b6fc 100644 --- a/chorus_lib/examples/tic-tac-toe.rs +++ b/chorus_lib/examples/tic-tac-toe.rs @@ -3,7 +3,8 @@ extern crate chorus_lib; use chorus_lib::{ core::{ - ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, ProjectorForAL, Serialize, + ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, ProjectorForAL, + Serialize, }, hlist, transport::http::HttpTransport, diff --git a/chorus_lib/src/core.rs b/chorus_lib/src/core.rs index f047cd0..5cc0a79 100644 --- a/chorus_lib/src/core.rs +++ b/chorus_lib/src/core.rs @@ -169,20 +169,20 @@ where } /// Equal - pub trait Equal {} +pub trait Equal {} - // Base case: HNil is equal to HNil - impl Equal for HNil {} +// Base case: HNil is equal to HNil +impl Equal for HNil {} - // Recursive case: Head::Tail is equal to L if - // 1. Head is a member of L - // 2. Tail is equal to the remainder of L - impl Equal> for HCons - where - Head: Member, - Tail: Equal, - { - } +// Recursive case: Head::Tail is equal to L if +// 1. Head is a member of L +// 2. Tail is equal to the remainder of L +impl Equal> for HCons +where + Head: Member, + Tail: Equal, +{ +} /// Provides a method to work with located values at the current location pub struct Unwrapper { @@ -287,8 +287,10 @@ pub trait Transport { } /// Provides a method to perform end-point projection. -pub struct Projector where - L1: Member{ +pub struct Projector +where + L1: Member, +{ target: PhantomData, transport: T, available_locations: PhantomData, @@ -314,15 +316,15 @@ impl ProjectorForAL { } } -impl Projector - where L1: Member +impl Projector +where + L1: Member, { /// Constructs a `Projector` struct. /// /// - `target` is the projection target of the choreography. /// - `transport` is an implementation of `Transport`. - pub fn new(_target: L1, transport: B) -> Self - { + pub fn new(_target: L1, transport: B) -> Self { Projector { target: PhantomData, transport, @@ -334,8 +336,7 @@ impl Projector(&self, value: V) -> Located - { + pub fn local(&self, value: V) -> Located { Located::local(value) } @@ -359,7 +360,10 @@ impl Projector, IndexSet>(&'a self, choreo: C) -> V + pub fn epp_and_run<'a, V, L: HList, C: Choreography, IndexSet>( + &'a self, + choreo: C, + ) -> V where L: Equal, { From ee676e55d6aeafdc396ef4a871a713db16d21d3f Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 07:25:17 -0700 Subject: [PATCH 04/11] Remove old comment --- chorus_lib/src/core.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/chorus_lib/src/core.rs b/chorus_lib/src/core.rs index 5cc0a79..5ae9dd6 100644 --- a/chorus_lib/src/core.rs +++ b/chorus_lib/src/core.rs @@ -343,8 +343,6 @@ where /// Constructs a `Located` struct *NOT* located at the projection target. /// /// Use this method to run a choreography that takes a located value as an input. - /// - /// Note that the method panics at runtime if the projection target and the location of the value are the same. pub fn remote(&self, _l2: L2) -> Located where L2: Member<>::Remainder, Index2>, From fbc4cab4a87d0078f4788ac1de2cc440835ef512 Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 09:30:26 -0700 Subject: [PATCH 05/11] Make the set of available-locations of Choreography be a subset of the Projector that uses it --- chorus_lib/src/core.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/chorus_lib/src/core.rs b/chorus_lib/src/core.rs index 5ae9dd6..6f53666 100644 --- a/chorus_lib/src/core.rs +++ b/chorus_lib/src/core.rs @@ -168,22 +168,6 @@ where { } -/// Equal -pub trait Equal {} - -// Base case: HNil is equal to HNil -impl Equal for HNil {} - -// Recursive case: Head::Tail is equal to L if -// 1. Head is a member of L -// 2. Tail is equal to the remainder of L -impl Equal> for HCons -where - Head: Member, - Tail: Equal, -{ -} - /// Provides a method to work with located values at the current location pub struct Unwrapper { phantom: PhantomData, @@ -363,7 +347,7 @@ where choreo: C, ) -> V where - L: Equal, + L: Subset, { struct EppOp<'a, L: HList, L1: ChoreographyLocation, B: Transport> { target: PhantomData, From 2f49ded1dd628b2a3befe622fdf2e29123930619 Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 11:32:13 -0700 Subject: [PATCH 06/11] Use a macro (projector) to instantiate Projectors --- chorus_lib/examples/bookseller.rs | 8 ++++---- chorus_lib/examples/bookseller2.rs | 10 +++++----- chorus_lib/examples/hello.rs | 8 ++++---- chorus_lib/examples/loc-poly.rs | 8 ++++---- chorus_lib/examples/tic-tac-toe.rs | 8 ++++---- chorus_lib/src/core.rs | 23 ++++++----------------- 6 files changed, 27 insertions(+), 38 deletions(-) diff --git a/chorus_lib/examples/bookseller.rs b/chorus_lib/examples/bookseller.rs index 16d1316..b93fc7a 100644 --- a/chorus_lib/examples/bookseller.rs +++ b/chorus_lib/examples/bookseller.rs @@ -3,10 +3,10 @@ extern crate chorus_lib; use std::io; use std::thread; -use chorus_lib::hlist; use chrono::NaiveDate; -use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, ProjectorForAL}; +use chorus_lib::{hlist, projector}; +use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; use chorus_lib::transport::local::LocalTransport; fn get_book(title: &str) -> Option<(i32, NaiveDate)> { @@ -75,8 +75,8 @@ impl Choreography for BooksellerChoreography { fn main() { let transport = LocalTransport::from(&[Seller::name(), Buyer::name()]); type AL = hlist!(Buyer, Seller); - let seller_projector = ProjectorForAL::::new(Seller, transport.clone()); - let buyer_projector = ProjectorForAL::::new(Buyer, transport.clone()); + let seller_projector = projector!(AL, Seller, transport.clone()); + let buyer_projector = projector!(AL, Buyer, transport.clone()); let mut handles: Vec> = Vec::new(); handles.push(thread::spawn(move || { diff --git a/chorus_lib/examples/bookseller2.rs b/chorus_lib/examples/bookseller2.rs index c72e94d..b20a512 100644 --- a/chorus_lib/examples/bookseller2.rs +++ b/chorus_lib/examples/bookseller2.rs @@ -3,9 +3,9 @@ extern crate chorus_lib; use std::thread; use std::{collections::HashMap, sync::Arc}; -use chorus_lib::hlist; +use chorus_lib::{hlist, projector}; use chorus_lib::{ - core::{ChoreoOp, Choreography, ChoreographyLocation, Located, ProjectorForAL}, + core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Projector}, transport::local::LocalTransport, }; use chrono::NaiveDate; @@ -144,9 +144,9 @@ fn main() { type AL = hlist!(Seller, Buyer1, Buyer2); let transport = LocalTransport::from(&[Seller::name(), Buyer1::name(), Buyer2::name()]); - let seller_projector = Arc::new(ProjectorForAL::::new(Seller, transport.clone())); - let buyer1_projector = Arc::new(ProjectorForAL::::new(Buyer1, transport.clone())); - let buyer2_projector = Arc::new(ProjectorForAL::::new(Buyer2, transport.clone())); + let seller_projector = Arc::new(projector!(AL, Seller, transport.clone())); + let buyer1_projector = Arc::new(projector!(AL, Buyer1, transport.clone())); + let buyer2_projector = Arc::new(projector!(AL, Buyer2, transport.clone())); println!("Tries to buy HoTT with one buyer"); type OneBuyerBooksellerChoreography = BooksellerChoreography; diff --git a/chorus_lib/examples/hello.rs b/chorus_lib/examples/hello.rs index cb51867..dbf283d 100644 --- a/chorus_lib/examples/hello.rs +++ b/chorus_lib/examples/hello.rs @@ -2,8 +2,8 @@ extern crate chorus_lib; use std::thread; -use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, ProjectorForAL}; -use chorus_lib::hlist; +use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; +use chorus_lib::{hlist, projector}; use chorus_lib::transport::local::LocalTransport; // --- Define two locations (Alice and Bob) --- @@ -48,14 +48,14 @@ fn main() { { let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = ProjectorForAL::::new(Alice, transport); + let p = projector!(AL, Alice, transport); p.epp_and_run(HelloWorldChoreography); })); } { let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = ProjectorForAL::::new(Bob, transport); + let p = projector!(AL, Bob, transport); p.epp_and_run(HelloWorldChoreography); })); } diff --git a/chorus_lib/examples/loc-poly.rs b/chorus_lib/examples/loc-poly.rs index 5b5613c..13e3bcd 100644 --- a/chorus_lib/examples/loc-poly.rs +++ b/chorus_lib/examples/loc-poly.rs @@ -3,9 +3,9 @@ use std::fmt::Debug; use std::thread; use chorus_lib::core::{ - ChoreoOp, Choreography, ChoreographyLocation, Located, Portable, ProjectorForAL, + ChoreoOp, Choreography, ChoreographyLocation, Located, Portable, Projector, }; -use chorus_lib::hlist; +use chorus_lib::{hlist, projector}; use chorus_lib::transport::local::LocalTransport; #[derive(ChoreographyLocation)] @@ -66,7 +66,7 @@ fn main() { { let transport = transport.clone(); handles.push(thread::spawn(|| { - let p = ProjectorForAL::::new(Alice, transport); + let p = projector!(AL, Alice, transport); let v = p.epp_and_run(MainChoreography); assert_eq!(p.unwrap(v), 110); })); @@ -74,7 +74,7 @@ fn main() { { let transport = transport.clone(); handles.push(thread::spawn(|| { - let p = ProjectorForAL::::new(Bob, transport); + let p = projector!(AL, Bob, transport); p.epp_and_run(MainChoreography); })); } diff --git a/chorus_lib/examples/tic-tac-toe.rs b/chorus_lib/examples/tic-tac-toe.rs index d53b6fc..65ba20e 100644 --- a/chorus_lib/examples/tic-tac-toe.rs +++ b/chorus_lib/examples/tic-tac-toe.rs @@ -3,10 +3,10 @@ extern crate chorus_lib; use chorus_lib::{ core::{ - ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, ProjectorForAL, + ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, Projector, Serialize, }, - hlist, + hlist, projector, transport::http::HttpTransport, }; use clap::Parser; @@ -304,7 +304,7 @@ fn main() { (args.opponent_hostname.as_str(), args.opponent_port), ); let transport = HttpTransport::new(PlayerX::name(), &config); - let projector = ProjectorForAL::::new(PlayerX, transport); + let projector = projector!(AL, PlayerX, transport); projector.epp_and_run(TicTacToeChoreography { brain_for_x: projector.local(brain), brain_for_o: projector.remote(PlayerO), @@ -318,7 +318,7 @@ fn main() { (args.opponent_hostname.as_str(), args.opponent_port), ); let transport = HttpTransport::new(PlayerO::name(), &config); - let projector = ProjectorForAL::::new(PlayerO, transport); + let projector = projector!(AL, PlayerO, transport); projector.epp_and_run(TicTacToeChoreography { brain_for_x: projector.remote(PlayerX), brain_for_o: projector.local(brain), diff --git a/chorus_lib/src/core.rs b/chorus_lib/src/core.rs index 6f53666..3f44deb 100644 --- a/chorus_lib/src/core.rs +++ b/chorus_lib/src/core.rs @@ -281,23 +281,12 @@ where index: PhantomData, } -/// Provides a wrapper struct for users so that they can only specify AL; since it can't be inferred. -pub struct ProjectorForAL(PhantomData); - -impl ProjectorForAL { - /// Constructs a `Projector` struct. - /// - /// - `target` is the projection target of the choreography. - /// - `transport` is an implementation of `Transport`. - pub fn new( - target: L1, - transport: B, - ) -> Projector - where - L1: Member, - { - Projector::new(target, transport) - } +/// Macro to make Projector +#[macro_export] +macro_rules! projector { + ($al_type:ty, $target:expr, $transport:expr) => { + Projector::<$al_type, _, _, _>::new($target, $transport) + }; } impl Projector From 0df1edce201ad26ddf43fc56a938308ee3db3de6 Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 11:38:17 -0700 Subject: [PATCH 07/11] Update the book to use the new projector macro --- chorus_book/src/guide-input-and-output.md | 15 ++++++++++----- chorus_book/src/guide-projector.md | 16 ++++++++++------ chorus_book/src/guide-transport.md | 8 ++++---- chorus_book/src/header.txt | 4 ++-- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/chorus_book/src/guide-input-and-output.md b/chorus_book/src/guide-input-and-output.md index 924ab98..e02b7f0 100644 --- a/chorus_book/src/guide-input-and-output.md +++ b/chorus_book/src/guide-input-and-output.md @@ -42,7 +42,8 @@ You can construct an instance of the choreography with the input and pass it to let choreo = DemoChoreography { input: "World".to_string(), }; -let projector = ProjectorForAL::::new(Alice, transport); +type AL = hlist!(Alice); +let projector = projector!(AL, Alice, transport); projector.epp_and_run(choreo); ``` @@ -92,7 +93,8 @@ To run the sample choreography above at Alice, we use the `local` method to cons # }); # } # } -let projector_for_alice = ProjectorForAL::::new(Alice, transport); +type AL = hlist!(Alice); +let projector_for_alice = projector!(AL, Alice, transport); // Because the target of the projector is Alice, the located value is available at Alice. let string_at_alice: Located = projector_for_alice.local("Hello, World!".to_string()); // Instantiate the choreography with the located value @@ -119,7 +121,8 @@ For Bob, we use the `remote` method to construct the located value. # }); # } # } -let projector_for_bob = ProjectorForAL::::new(Bob, transport); +type AL = hlist!(Alice, Bob); +let projector_for_bob = projector!(AL, Bob, transport); // Construct a remote located value at Alice. The actual value is not required. let string_at_alice = projector_for_bob.remote(Alice); // Instantiate the choreography with the located value @@ -160,7 +163,8 @@ impl Choreography for DemoChoreography { # } # } let choreo = DemoChoreography; -let projector = ProjectorForAL::::new(Alice, transport); +type AL = hlist!(Alice); +let projector = projector!(AL, Alice, transport); let output = projector.epp_and_run(choreo); assert_eq!(output, "Hello, World!".to_string()); ``` @@ -182,7 +186,8 @@ impl Choreography> for DemoChoreography { } } -let projector = ProjectorForAL::::new(Alice, transport); +type AL = hlist!(Alice); +let projector = projector!(AL, Alice, transport); let output = projector.epp_and_run(DemoChoreography); let string_at_alice = projector.unwrap(output); assert_eq!(string_at_alice, "Hello, World!".to_string()); diff --git a/chorus_book/src/guide-projector.md b/chorus_book/src/guide-projector.md index c56e632..d9bbba3 100644 --- a/chorus_book/src/guide-projector.md +++ b/chorus_book/src/guide-projector.md @@ -9,15 +9,17 @@ To create a `Projector`, you need to provide the location and the transport. ```rust # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; -# use chorus_lib::core::{ChoreographyLocation, ProjectorForAL}; -# use chorus_lib::hlist; +# use chorus_lib::core::{ChoreographyLocation, Projector}; +# use chorus_lib::{hlist, projector}; # let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); # #[derive(ChoreographyLocation)] # struct Alice; # #[derive(ChoreographyLocation)] # struct Bob; # -let projector = ProjectorForAL::::new(Alice, transport); + +type AL = hlist!(Alice, Bob); +let projector = projector!(AL, Alice, transport); ``` Notice that the `Projector` is parameterized by the location type. You will need one projector for each location to execute choreography. @@ -29,8 +31,8 @@ To execute a choreography, you need to call the `epp_and_run` method on the `Pro ```rust # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; -# use chorus_lib::core::{ChoreographyLocation, ProjectorForAL, Choreography, ChoreoOp}; -# use chorus_lib::hlist; +# use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp}; +# use chorus_lib::{hlist, projector}; # let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); # #[derive(ChoreographyLocation)] # struct Alice; @@ -43,7 +45,9 @@ To execute a choreography, you need to call the `epp_and_run` method on the `Pro # } # } # -# let projector = ProjectorForAL::::new(Alice, transport); + +# type AL = hlist!(Alice); +# let projector = projector!(AL, Alice, transport); projector.epp_and_run(HelloWorldChoreography); ``` diff --git a/chorus_book/src/guide-transport.md b/chorus_book/src/guide-transport.md index 01c7b90..5d86e5a 100644 --- a/chorus_book/src/guide-transport.md +++ b/chorus_book/src/guide-transport.md @@ -25,8 +25,8 @@ Because of the nature of the `Local` transport, you must use the same `LocalTran # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; # use std::thread; -# use chorus_lib::core::{ChoreographyLocation, ChoreoOp, Choreography, ProjectorForAL}; -# use chorus_lib::hlist; +# use chorus_lib::core::{ChoreographyLocation, ChoreoOp, Choreography, Projector}; +# use chorus_lib::{hlist, projector}; # #[derive(ChoreographyLocation)] # struct Alice; # #[derive(ChoreographyLocation)] @@ -47,7 +47,7 @@ let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); // create a clone for Alice let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = ProjectorForAL::::new(Alice, transport); + let p = projector!(AL, Alice, transport); p.epp_and_run(HelloWorldChoreography); })); } @@ -55,7 +55,7 @@ let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); // create another for Bob let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = ProjectorForAL::::new(Bob, transport); + let p = projector!(AL, Bob, transport); p.epp_and_run(HelloWorldChoreography); })); } diff --git a/chorus_book/src/header.txt b/chorus_book/src/header.txt index 6c1f207..4a0c7eb 100644 --- a/chorus_book/src/header.txt +++ b/chorus_book/src/header.txt @@ -1,7 +1,7 @@ # extern crate chorus_lib; -# use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, ProjectorForAL, Located, Superposition, Runner}; +# use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector, Located, Superposition, Runner}; # use chorus_lib::transport::local::LocalTransport; -# use chorus_lib::hlist; +# use chorus_lib::{hlist, projector}; # #[derive(ChoreographyLocation)] # struct Alice; # #[derive(ChoreographyLocation)] From a18ee9201069a90e19753f01a1ce0a477ba38402 Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 11:38:48 -0700 Subject: [PATCH 08/11] Format code --- chorus_lib/examples/bookseller.rs | 2 +- chorus_lib/examples/bookseller2.rs | 2 +- chorus_lib/examples/hello.rs | 2 +- chorus_lib/examples/loc-poly.rs | 2 +- chorus_lib/examples/tic-tac-toe.rs | 3 +-- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/chorus_lib/examples/bookseller.rs b/chorus_lib/examples/bookseller.rs index b93fc7a..ead5e2a 100644 --- a/chorus_lib/examples/bookseller.rs +++ b/chorus_lib/examples/bookseller.rs @@ -5,9 +5,9 @@ use std::thread; use chrono::NaiveDate; -use chorus_lib::{hlist, projector}; use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; use chorus_lib::transport::local::LocalTransport; +use chorus_lib::{hlist, projector}; fn get_book(title: &str) -> Option<(i32, NaiveDate)> { match title.trim() { diff --git a/chorus_lib/examples/bookseller2.rs b/chorus_lib/examples/bookseller2.rs index b20a512..89b9e76 100644 --- a/chorus_lib/examples/bookseller2.rs +++ b/chorus_lib/examples/bookseller2.rs @@ -3,11 +3,11 @@ extern crate chorus_lib; use std::thread; use std::{collections::HashMap, sync::Arc}; -use chorus_lib::{hlist, projector}; use chorus_lib::{ core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Projector}, transport::local::LocalTransport, }; +use chorus_lib::{hlist, projector}; use chrono::NaiveDate; #[derive(ChoreographyLocation)] diff --git a/chorus_lib/examples/hello.rs b/chorus_lib/examples/hello.rs index dbf283d..41fb50b 100644 --- a/chorus_lib/examples/hello.rs +++ b/chorus_lib/examples/hello.rs @@ -3,8 +3,8 @@ extern crate chorus_lib; use std::thread; use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; -use chorus_lib::{hlist, projector}; use chorus_lib::transport::local::LocalTransport; +use chorus_lib::{hlist, projector}; // --- Define two locations (Alice and Bob) --- diff --git a/chorus_lib/examples/loc-poly.rs b/chorus_lib/examples/loc-poly.rs index 13e3bcd..3b216a7 100644 --- a/chorus_lib/examples/loc-poly.rs +++ b/chorus_lib/examples/loc-poly.rs @@ -5,8 +5,8 @@ use std::thread; use chorus_lib::core::{ ChoreoOp, Choreography, ChoreographyLocation, Located, Portable, Projector, }; -use chorus_lib::{hlist, projector}; use chorus_lib::transport::local::LocalTransport; +use chorus_lib::{hlist, projector}; #[derive(ChoreographyLocation)] struct Alice; diff --git a/chorus_lib/examples/tic-tac-toe.rs b/chorus_lib/examples/tic-tac-toe.rs index 65ba20e..aae2dc8 100644 --- a/chorus_lib/examples/tic-tac-toe.rs +++ b/chorus_lib/examples/tic-tac-toe.rs @@ -3,8 +3,7 @@ extern crate chorus_lib; use chorus_lib::{ core::{ - ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, Projector, - Serialize, + ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, Projector, Serialize, }, hlist, projector, transport::http::HttpTransport, From 03262eae2e636a9e80f82dbb0417900a7a669791 Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 11:52:36 -0700 Subject: [PATCH 09/11] Update the book for Projector --- chorus_book/src/guide-projector.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/chorus_book/src/guide-projector.md b/chorus_book/src/guide-projector.md index d9bbba3..6679012 100644 --- a/chorus_book/src/guide-projector.md +++ b/chorus_book/src/guide-projector.md @@ -4,7 +4,7 @@ Projector is responsible for performing the end-point projection and executing t ## Creating a Projector -To create a `Projector`, you need to provide the location and the transport. +To create a `Projector`, you need to provide the set of locations it can work with, the target location, and the transport. ```rust # extern crate chorus_lib; @@ -52,3 +52,30 @@ projector.epp_and_run(HelloWorldChoreography); ``` If the choreography has a return value, the `epp_and_run` method will return the value. We will discuss the return values in the [Input and Output](./guide-input-and-output.md) section. + +### Note on the available location set of the Choreography + +Keep in mind that when calling `epp_and_run`, you will get a compile error if the set of available locations of the `Choreography` is not a subset of the available locations of the `Projector`. In other words, the `Projector` should be allowed to do end-point projection into every `ChoreographyLocation` there is in the `Choreography`. So this will fail: + +```rust, compile_fail +# extern crate chorus_lib; +# use chorus_lib::transport::local::LocalTransport; +# use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp}; +# use chorus_lib::{hlist, projector}; +# let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); +# #[derive(ChoreographyLocation)] +# struct Alice; +# #[derive(ChoreographyLocation)] +# struct Bob; +struct HelloWorldChoreography; +impl Choreography for HelloWorldChoreography { + type L = hlist!(Alice, Bob); + fn run(self, op: &impl ChoreoOp) { + } +} + + +type AL = hlist!(Alice); +let projector = projector!(AL, Alice, transport); +projector.epp_and_run(HelloWorldChoreography); +``` From 11d74a1d76af97357c3e936b7b2ae36572135a55 Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 14:02:46 -0700 Subject: [PATCH 10/11] Change the the wording from available locations to location set --- chorus_book/src/guide-choreography.md | 18 +++++----- chorus_book/src/guide-colocally.md | 12 +++---- .../src/guide-higher-order-choreography.md | 8 ++--- chorus_book/src/guide-input-and-output.md | 32 ++++++++---------- .../src/guide-location-polymorphism.md | 2 +- chorus_book/src/guide-projector.md | 24 ++++++-------- chorus_book/src/guide-runner.md | 4 +-- chorus_book/src/guide-transport.md | 10 +++--- chorus_book/src/header.txt | 2 +- chorus_lib/examples/bookseller.rs | 11 +++---- chorus_lib/examples/bookseller2.rs | 33 ++++++++++++------- chorus_lib/examples/hello.rs | 12 +++---- chorus_lib/examples/input-output.rs | 4 +-- chorus_lib/examples/loc-poly.rs | 18 ++++------ chorus_lib/examples/runner.rs | 6 ++-- chorus_lib/examples/tic-tac-toe.rs | 16 ++++----- chorus_lib/src/core.rs | 22 ++++++------- 17 files changed, 111 insertions(+), 123 deletions(-) diff --git a/chorus_book/src/guide-choreography.md b/chorus_book/src/guide-choreography.md index 5474ccb..32003c3 100644 --- a/chorus_book/src/guide-choreography.md +++ b/chorus_book/src/guide-choreography.md @@ -9,7 +9,7 @@ struct HelloWorldChoreography; // 2. Implement the `Choreography` trait impl Choreography for HelloWorldChoreography { - type L = hlist!(Alice); + type L = LocationSet!(Alice); fn run(self, op: &impl ChoreoOp) { // 3. Use the `op` parameter to access operators op.locally(Alice, |_| { @@ -21,7 +21,7 @@ impl Choreography for HelloWorldChoreography { `Choreography` must implement the `run` method which defines the behavior of the system. The `run` method takes a reference to an object that implements the `ChoreoOp` trait. The `ChoreoOp` trait provides choreographic operators such as `locally` and `comm`. -Also, each `Choreography` has an associated type `L`, which is the set of `ChoreographyLocation`s it can operate on. To build a set of locations, you can use the macro `hlist!`. +Also, each `Choreography` has an associated type `L`, called it's location set; this is the set of `ChoreographyLocation`s that the `Choreography` can operate on. To build a location set, you can use the macro `LocationSet!`. ## Choreographic Operators @@ -36,7 +36,7 @@ The `locally` operator is used to perform a computation at a single location. It # # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) { op.locally(Alice, |_| { println!("Hello, World!"); @@ -52,7 +52,7 @@ The closure can return a value to create a located value. Located values are val # # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) { // This value is only available at Alice let num_at_alice: Located = op.locally(Alice, |_| { @@ -69,7 +69,7 @@ The computation closure takes `Unwrapper`. Using the `Unwrapper`, you can get a # # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) { let num_at_alice: Located = op.locally(Alice, |_| { 42 @@ -90,7 +90,7 @@ Note that you can unwrap a located value only at the location where the located # # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice, Bob); +# type L = LocationSet!(Alice, Bob); # fn run(self, op: &impl ChoreoOp) { // This code will fail to compile let num_at_alice = op.locally(Alice, |_| { 42 }); @@ -113,7 +113,7 @@ The `comm` operator is used to perform a communication between two locations. It # # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice, Bob); +# type L = LocationSet!(Alice, Bob); # fn run(self, op: &impl ChoreoOp) { // This value is only available at Alice let num_at_alice: Located = op.locally(Alice, |_| { @@ -139,7 +139,7 @@ The `broadcast` operator is used to perform a broadcast from a single location t # # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) { // This value is only available at Alice let num_at_alice: Located = op.locally(Alice, |_| { @@ -173,7 +173,7 @@ You'll get a compile error if you try to work with a `ChoreographyLocation` that # // 2. Implement the `Choreography` trait // ... impl Choreography for HelloWorldChoreography { - type L = hlist!(Alice); + type L = LocationSet!(Alice); fn run(self, op: &impl ChoreoOp) { // this will fail op.locally(Bob, |_| { diff --git a/chorus_book/src/guide-colocally.md b/chorus_book/src/guide-colocally.md index 8ad18fd..d563bc5 100644 --- a/chorus_book/src/guide-colocally.md +++ b/chorus_book/src/guide-colocally.md @@ -20,7 +20,7 @@ This protocol can be implemented as follows: struct DemoChoreography; impl Choreography for DemoChoreography { - type L = hlist!(Alice, Bob, Carol); + type L = LocationSet!(Alice, Bob, Carol); fn run(self, op: &impl ChoreoOp) { let x_at_alice = op.locally(Alice, |_| { get_random_number() @@ -52,7 +52,7 @@ struct BobCarolChoreography { x_at_bob: Located, }; impl Choreography for BobCarolChoreography { - type L = hlist!(Bob, Carol); + type L = LocationSet!(Bob, Carol); fn run(self, op: &impl ChoreoOp) { let is_even_at_bob: Located = op.locally(Bob, |un| { let x = un.unwrap(&self.x_at_bob); @@ -81,7 +81,7 @@ Notice that `BobCarolChoreography` only describes the behavior of Bob and Carol # x_at_bob: Located, # }; # impl Choreography for BobCarolChoreography { -# type L = hlist!(Bob, Carol); +# type L = LocationSet!(Bob, Carol); # fn run(self, op: &impl ChoreoOp) { # let is_even_at_bob: Located = op.locally(Bob, |un| { # let x = un.unwrap(&self.x_at_bob); @@ -99,7 +99,7 @@ Notice that `BobCarolChoreography` only describes the behavior of Bob and Carol # } struct MainChoreography; impl Choreography for MainChoreography { - type L = hlist!(Alice, Bob, Carol); + type L = LocationSet!(Alice, Bob, Carol); fn run(self, op: &impl ChoreoOp) { let x_at_alice = op.locally(Alice, |_| { get_random_number() @@ -135,7 +135,7 @@ struct BobCarolChoreography { }; impl Choreography for BobCarolChoreography { - type L = hlist!(Bob, Carol); + type L = LocationSet!(Bob, Carol); fn run(self, op: &impl ChoreoOp) -> BobCarolResult { let is_even_at_bob: Located = op.locally(Bob, |un| { let x = un.unwrap(&self.x_at_bob); @@ -159,7 +159,7 @@ impl Choreography for BobCarolChoreography { struct MainChoreography; impl Choreography for MainChoreography { - type L = hlist!(Alice, Bob, Carol); + type L = LocationSet!(Alice, Bob, Carol); fn run(self, op: &impl ChoreoOp) { let x_at_alice = op.locally(Alice, |_| { get_random_number() diff --git a/chorus_book/src/guide-higher-order-choreography.md b/chorus_book/src/guide-higher-order-choreography.md index 588f9e5..d7c1750 100644 --- a/chorus_book/src/guide-higher-order-choreography.md +++ b/chorus_book/src/guide-higher-order-choreography.md @@ -22,8 +22,8 @@ When you implement the `Choreography` trait, you have access to the `sub_choreo` # struct HigherOrderChoreography { # sub_choreo: C, # }; -impl> Choreography for HigherOrderChoreography { - type L = hlist!(Alice, Bob); +impl> Choreography for HigherOrderChoreography { + type L = LocationSet!(Alice, Bob); fn run(self, op: &impl ChoreoOp) { op.call(self.sub_choreo); } @@ -46,8 +46,8 @@ struct HigherOrderChoreography> + SubChoreo _marker: PhantomData, }; -impl, L = hlist!(Alice)> + SubChoreography> Choreography for HigherOrderChoreography { - type L = hlist!(Alice); +impl, L = LocationSet!(Alice)> + SubChoreography> Choreography for HigherOrderChoreography { + type L = LocationSet!(Alice); fn run(self, op: &impl ChoreoOp) { let num_at_alice = op.locally(Alice, |_| { 42 diff --git a/chorus_book/src/guide-input-and-output.md b/chorus_book/src/guide-input-and-output.md index e02b7f0..25bd8ea 100644 --- a/chorus_book/src/guide-input-and-output.md +++ b/chorus_book/src/guide-input-and-output.md @@ -18,7 +18,7 @@ struct DemoChoreography { } impl Choreography for DemoChoreography { - type L = hlist!(); + type L = LocationSet!(); fn run(self, op: &impl ChoreoOp) { println!("Input: {}", self.input); } @@ -33,7 +33,7 @@ You can construct an instance of the choreography with the input and pass it to # input: String, # } # impl Choreography for DemoChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) { # println!("Input: {}", self.input); # } @@ -42,8 +42,8 @@ You can construct an instance of the choreography with the input and pass it to let choreo = DemoChoreography { input: "World".to_string(), }; -type AL = hlist!(Alice); -let projector = projector!(AL, Alice, transport); + +let projector = projector!(LocationSet!(Alice), Alice, transport); projector.epp_and_run(choreo); ``` @@ -58,7 +58,7 @@ struct DemoChoreography { } impl Choreography for DemoChoreography { - type L = hlist!(Alice); + type L = LocationSet!(Alice); fn run(self, op: &impl ChoreoOp) { op.locally(Alice, |un| { let input = un.unwrap(&self.input); @@ -85,7 +85,7 @@ To run the sample choreography above at Alice, we use the `local` method to cons # } # # impl Choreography for DemoChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) { # op.locally(Alice, |un| { # let input = un.unwrap(&self.input); @@ -93,8 +93,7 @@ To run the sample choreography above at Alice, we use the `local` method to cons # }); # } # } -type AL = hlist!(Alice); -let projector_for_alice = projector!(AL, Alice, transport); +let projector_for_alice = projector!(LocationSet!(Alice), Alice, transport); // Because the target of the projector is Alice, the located value is available at Alice. let string_at_alice: Located = projector_for_alice.local("Hello, World!".to_string()); // Instantiate the choreography with the located value @@ -113,7 +112,7 @@ For Bob, we use the `remote` method to construct the located value. # } # # impl Choreography for DemoChoreography { -# type L = hlist!(Alice, Bob); +# type L = LocationSet!(Alice, Bob); # fn run(self, op: &impl ChoreoOp) { # op.locally(Alice, |un| { # let input = un.unwrap(&self.input); @@ -121,8 +120,7 @@ For Bob, we use the `remote` method to construct the located value. # }); # } # } -type AL = hlist!(Alice, Bob); -let projector_for_bob = projector!(AL, Bob, transport); +let projector_for_bob = projector!(LocationSet!(Alice, Bob), Bob, transport); // Construct a remote located value at Alice. The actual value is not required. let string_at_alice = projector_for_bob.remote(Alice); // Instantiate the choreography with the located value @@ -143,7 +141,7 @@ To do so, we specify the output type to the `Choreography` trait and return the struct DemoChoreography; impl Choreography for DemoChoreography { - type L = hlist!(); + type L = LocationSet!(); fn run(self, op: &impl ChoreoOp) -> String { "Hello, World!".to_string() } @@ -157,14 +155,13 @@ impl Choreography for DemoChoreography { # struct DemoChoreography; # # impl Choreography for DemoChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) -> String { # "Hello, World!".to_string() # } # } let choreo = DemoChoreography; -type AL = hlist!(Alice); -let projector = projector!(AL, Alice, transport); +let projector = projector!(LocationSet!(Alice), Alice, transport); let output = projector.epp_and_run(choreo); assert_eq!(output, "Hello, World!".to_string()); ``` @@ -178,7 +175,7 @@ You can use the `Located` as a return type of the `run` method to return struct DemoChoreography; impl Choreography> for DemoChoreography { - type L = hlist!(Alice); + type L = LocationSet!(Alice); fn run(self, op: &impl ChoreoOp) -> Located { op.locally(Alice, |_| { "Hello, World!".to_string() @@ -186,8 +183,7 @@ impl Choreography> for DemoChoreography { } } -type AL = hlist!(Alice); -let projector = projector!(AL, Alice, transport); +let projector = projector!(LocationSet!(Alice), Alice, transport); let output = projector.epp_and_run(DemoChoreography); let string_at_alice = projector.unwrap(output); assert_eq!(string_at_alice, "Hello, World!".to_string()); diff --git a/chorus_book/src/guide-location-polymorphism.md b/chorus_book/src/guide-location-polymorphism.md index ebe7d6a..ef0ef1f 100644 --- a/chorus_book/src/guide-location-polymorphism.md +++ b/chorus_book/src/guide-location-polymorphism.md @@ -11,7 +11,7 @@ struct LocationPolymorphicChoreography { } impl Choreography for LocationPolymorphicChoreography { - type L = hlist!(L1); + type L = LocationSet!(L1); fn run(self, op: &impl ChoreoOp) { op.locally(self.location, |_| { println!("Hello, World!"); diff --git a/chorus_book/src/guide-projector.md b/chorus_book/src/guide-projector.md index 6679012..8b32821 100644 --- a/chorus_book/src/guide-projector.md +++ b/chorus_book/src/guide-projector.md @@ -10,7 +10,7 @@ To create a `Projector`, you need to provide the set of locations it can work wi # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; # use chorus_lib::core::{ChoreographyLocation, Projector}; -# use chorus_lib::{hlist, projector}; +# use chorus_lib::{LocationSet, projector}; # let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); # #[derive(ChoreographyLocation)] # struct Alice; @@ -18,8 +18,7 @@ To create a `Projector`, you need to provide the set of locations it can work wi # struct Bob; # -type AL = hlist!(Alice, Bob); -let projector = projector!(AL, Alice, transport); +let projector = projector!(LocationSet!(Alice, Bob), Alice, transport); ``` Notice that the `Projector` is parameterized by the location type. You will need one projector for each location to execute choreography. @@ -32,7 +31,7 @@ To execute a choreography, you need to call the `epp_and_run` method on the `Pro # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; # use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp}; -# use chorus_lib::{hlist, projector}; +# use chorus_lib::{LocationSet, projector}; # let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); # #[derive(ChoreographyLocation)] # struct Alice; @@ -40,28 +39,27 @@ To execute a choreography, you need to call the `epp_and_run` method on the `Pro # struct Bob; # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice); +# type L = LocationSet!(Alice); # fn run(self, op: &impl ChoreoOp) { # } # } # -# type AL = hlist!(Alice); -# let projector = projector!(AL, Alice, transport); +# let projector = projector!(LocationSet!(Alice), Alice, transport); projector.epp_and_run(HelloWorldChoreography); ``` If the choreography has a return value, the `epp_and_run` method will return the value. We will discuss the return values in the [Input and Output](./guide-input-and-output.md) section. -### Note on the available location set of the Choreography +### Note on the location set of the Choreography -Keep in mind that when calling `epp_and_run`, you will get a compile error if the set of available locations of the `Choreography` is not a subset of the available locations of the `Projector`. In other words, the `Projector` should be allowed to do end-point projection into every `ChoreographyLocation` there is in the `Choreography`. So this will fail: +Keep in mind that when calling `epp_and_run`, you will get a compile error if the location set of the `Choreography` is not a subset of the location set of the `Projector`. In other words, the `Projector` should be allowed to do end-point projection into every `ChoreographyLocation` that `Choreography` can talk about. So this will fail: ```rust, compile_fail # extern crate chorus_lib; # use chorus_lib::transport::local::LocalTransport; # use chorus_lib::core::{ChoreographyLocation, Projector, Choreography, ChoreoOp}; -# use chorus_lib::{hlist, projector}; +# use chorus_lib::{LocationSet, projector}; # let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); # #[derive(ChoreographyLocation)] # struct Alice; @@ -69,13 +67,11 @@ Keep in mind that when calling `epp_and_run`, you will get a compile error if th # struct Bob; struct HelloWorldChoreography; impl Choreography for HelloWorldChoreography { - type L = hlist!(Alice, Bob); + type L = LocationSet!(Alice, Bob); fn run(self, op: &impl ChoreoOp) { } } - -type AL = hlist!(Alice); -let projector = projector!(AL, Alice, transport); +let projector = projector!(LocationSet!(Alice), Alice, transport); projector.epp_and_run(HelloWorldChoreography); ``` diff --git a/chorus_book/src/guide-runner.md b/chorus_book/src/guide-runner.md index 6d43d1e..1f501ff 100644 --- a/chorus_book/src/guide-runner.md +++ b/chorus_book/src/guide-runner.md @@ -8,7 +8,7 @@ To use `Runner`, construct an instance using the `new` constructor, and then cal {{#include ./header.txt}} # struct DemoChoreography; # impl Choreography for DemoChoreography { -# type L = hlist!(); +# type L = LocationSet!(); # fn run(self, op: &impl ChoreoOp) { # } # } @@ -27,7 +27,7 @@ struct SumChoreography { y_at_bob: Located, } impl Choreography> for SumChoreography { - type L = hlist!(Alice, Bob, Carol); + type L = LocationSet!(Alice, Bob, Carol); fn run(self, op: &impl ChoreoOp) -> Located { let x_at_carol = op.comm(Alice, Carol, &self.x_at_alice); let y_at_carol = op.comm(Bob, Carol, &self.y_at_bob); diff --git a/chorus_book/src/guide-transport.md b/chorus_book/src/guide-transport.md index 5d86e5a..310a533 100644 --- a/chorus_book/src/guide-transport.md +++ b/chorus_book/src/guide-transport.md @@ -26,20 +26,18 @@ Because of the nature of the `Local` transport, you must use the same `LocalTran # use chorus_lib::transport::local::LocalTransport; # use std::thread; # use chorus_lib::core::{ChoreographyLocation, ChoreoOp, Choreography, Projector}; -# use chorus_lib::{hlist, projector}; +# use chorus_lib::{LocationSet, projector}; # #[derive(ChoreographyLocation)] # struct Alice; # #[derive(ChoreographyLocation)] # struct Bob; # struct HelloWorldChoreography; # impl Choreography for HelloWorldChoreography { -# type L = hlist!(Alice, Bob); +# type L = LocationSet!(Alice, Bob); # fn run(self, op: &impl ChoreoOp) { # } # } -// Crate available locations for Projector -type AL = hlist!(Alice, Bob); let mut handles: Vec> = Vec::new(); let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); @@ -47,7 +45,7 @@ let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); // create a clone for Alice let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = projector!(AL, Alice, transport); + let p = projector!(LocationSet!(Alice, Bob), Alice, transport); p.epp_and_run(HelloWorldChoreography); })); } @@ -55,7 +53,7 @@ let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); // create another for Bob let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = projector!(AL, Bob, transport); + let p = projector!(LocationSet!(Alice, Bob), Bob, transport); p.epp_and_run(HelloWorldChoreography); })); } diff --git a/chorus_book/src/header.txt b/chorus_book/src/header.txt index 4a0c7eb..2115638 100644 --- a/chorus_book/src/header.txt +++ b/chorus_book/src/header.txt @@ -1,7 +1,7 @@ # extern crate chorus_lib; # use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector, Located, Superposition, Runner}; # use chorus_lib::transport::local::LocalTransport; -# use chorus_lib::{hlist, projector}; +# use chorus_lib::{LocationSet, projector}; # #[derive(ChoreographyLocation)] # struct Alice; # #[derive(ChoreographyLocation)] diff --git a/chorus_lib/examples/bookseller.rs b/chorus_lib/examples/bookseller.rs index ead5e2a..39d7c20 100644 --- a/chorus_lib/examples/bookseller.rs +++ b/chorus_lib/examples/bookseller.rs @@ -5,9 +5,9 @@ use std::thread; use chrono::NaiveDate; -use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; +use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation}; use chorus_lib::transport::local::LocalTransport; -use chorus_lib::{hlist, projector}; +use chorus_lib::{projector, LocationSet}; fn get_book(title: &str) -> Option<(i32, NaiveDate)> { match title.trim() { @@ -27,7 +27,7 @@ struct Buyer; struct BooksellerChoreography; impl Choreography for BooksellerChoreography { - type L = hlist!(Seller, Buyer); + type L = LocationSet!(Seller, Buyer); fn run(self, op: &impl ChoreoOp) { let title_at_buyer = op.locally(Buyer, |_| { println!("Enter the title of the book to buy (TAPL or HoTT)"); @@ -74,9 +74,8 @@ impl Choreography for BooksellerChoreography { fn main() { let transport = LocalTransport::from(&[Seller::name(), Buyer::name()]); - type AL = hlist!(Buyer, Seller); - let seller_projector = projector!(AL, Seller, transport.clone()); - let buyer_projector = projector!(AL, Buyer, transport.clone()); + let seller_projector = projector!(LocationSet!(Buyer, Seller), Seller, transport.clone()); + let buyer_projector = projector!(LocationSet!(Buyer, Seller), Buyer, transport.clone()); let mut handles: Vec> = Vec::new(); handles.push(thread::spawn(move || { diff --git a/chorus_lib/examples/bookseller2.rs b/chorus_lib/examples/bookseller2.rs index 89b9e76..ca6f68f 100644 --- a/chorus_lib/examples/bookseller2.rs +++ b/chorus_lib/examples/bookseller2.rs @@ -4,10 +4,10 @@ use std::thread; use std::{collections::HashMap, sync::Arc}; use chorus_lib::{ - core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Projector}, + core::{ChoreoOp, Choreography, ChoreographyLocation, Located}, transport::local::LocalTransport, }; -use chorus_lib::{hlist, projector}; +use chorus_lib::{projector, LocationSet}; use chrono::NaiveDate; #[derive(ChoreographyLocation)] @@ -36,7 +36,7 @@ impl Decider for OneBuyerDecider { } impl Choreography> for OneBuyerDecider { - type L = hlist!(Buyer1, Buyer2); + type L = LocationSet!(Buyer1, Buyer2); fn run(self, op: &impl ChoreoOp) -> Located { let price = op.broadcast(Buyer1, self.price); return op.locally(Buyer1, |_| { @@ -57,7 +57,7 @@ impl Decider for TwoBuyerDecider { } impl Choreography> for TwoBuyerDecider { - type L = hlist!(Buyer1, Buyer2); + type L = LocationSet!(Buyer1, Buyer2); fn run(self, op: &impl ChoreoOp) -> Located { let remaining = op.locally(Buyer1, |un| { const BUYER1_BUDGET: i32 = 100; @@ -79,10 +79,10 @@ struct BooksellerChoreography>> { title: Located, } -impl, L = hlist!(Buyer1, Buyer2)> + Decider> +impl, L = LocationSet!(Buyer1, Buyer2)> + Decider> Choreography, Buyer1>> for BooksellerChoreography { - type L = hlist!(Buyer1, Buyer2, Seller); + type L = LocationSet!(Buyer1, Buyer2, Seller); fn run(self, op: &impl ChoreoOp) -> Located, Buyer1> { let title_at_seller = op.comm(Buyer1, Seller, &self.title); let price_at_seller = op.locally(Seller, |un| { @@ -102,7 +102,7 @@ impl, L = hlist!(Buyer1, Buyer2)> + Decide decision_at_buyer1: Located, } impl Choreography, Buyer1>> for GetDeliveryDateChoreography { - type L = hlist!(Buyer1, Seller); + type L = LocationSet!(Buyer1, Seller); fn run(self, op: &impl ChoreoOp) -> Located, Buyer1> { let decision = op.broadcast(Buyer1, self.decision_at_buyer1); if decision { @@ -142,11 +142,22 @@ fn main() { i }; - type AL = hlist!(Seller, Buyer1, Buyer2); let transport = LocalTransport::from(&[Seller::name(), Buyer1::name(), Buyer2::name()]); - let seller_projector = Arc::new(projector!(AL, Seller, transport.clone())); - let buyer1_projector = Arc::new(projector!(AL, Buyer1, transport.clone())); - let buyer2_projector = Arc::new(projector!(AL, Buyer2, transport.clone())); + let seller_projector = Arc::new(projector!( + LocationSet!(Seller, Buyer1, Buyer2), + Seller, + transport.clone() + )); + let buyer1_projector = Arc::new(projector!( + LocationSet!(Seller, Buyer1, Buyer2), + Buyer1, + transport.clone() + )); + let buyer2_projector = Arc::new(projector!( + LocationSet!(Seller, Buyer1, Buyer2), + Buyer2, + transport.clone() + )); println!("Tries to buy HoTT with one buyer"); type OneBuyerBooksellerChoreography = BooksellerChoreography; diff --git a/chorus_lib/examples/hello.rs b/chorus_lib/examples/hello.rs index 41fb50b..bac0aff 100644 --- a/chorus_lib/examples/hello.rs +++ b/chorus_lib/examples/hello.rs @@ -2,9 +2,9 @@ extern crate chorus_lib; use std::thread; -use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Projector}; +use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation}; use chorus_lib::transport::local::LocalTransport; -use chorus_lib::{hlist, projector}; +use chorus_lib::{projector, LocationSet}; // --- Define two locations (Alice and Bob) --- @@ -19,7 +19,7 @@ struct HelloWorldChoreography; // Implement the `Choreography` trait for `HelloWorldChoreography` impl Choreography for HelloWorldChoreography { - type L = hlist!(Alice, Bob); + type L = LocationSet!(Alice, Bob); fn run(self, op: &impl ChoreoOp) { // Create a located value at Alice let msg_at_alice = op.locally(Alice, |_| { @@ -41,21 +41,19 @@ fn main() { let mut handles: Vec> = Vec::new(); // Create a local transport let transport = LocalTransport::from(&[Alice::name(), Bob::name()]); - // Crate available locations for Projector - type AL = hlist!(Alice, Bob); // Run the choreography in two threads { let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = projector!(AL, Alice, transport); + let p = projector!(LocationSet!(Alice, Bob), Alice, transport); p.epp_and_run(HelloWorldChoreography); })); } { let transport = transport.clone(); handles.push(thread::spawn(move || { - let p = projector!(AL, Bob, transport); + let p = projector!(LocationSet!(Alice, Bob), Bob, transport); p.epp_and_run(HelloWorldChoreography); })); } diff --git a/chorus_lib/examples/input-output.rs b/chorus_lib/examples/input-output.rs index 7b77bab..a02844b 100644 --- a/chorus_lib/examples/input-output.rs +++ b/chorus_lib/examples/input-output.rs @@ -1,7 +1,7 @@ extern crate chorus_lib; use chorus_lib::{ core::{ChoreoOp, Choreography, ChoreographyLocation, Located}, - hlist, + LocationSet, }; #[derive(ChoreographyLocation)] struct Alice; @@ -15,7 +15,7 @@ struct DemoChoreography { } impl Choreography for DemoChoreography { - type L = hlist!(Alice); + type L = LocationSet!(Alice); fn run(self, op: &impl ChoreoOp) { op.locally(Alice, |un| { let s = un.unwrap(&self.input); diff --git a/chorus_lib/examples/loc-poly.rs b/chorus_lib/examples/loc-poly.rs index 3b216a7..88a56a9 100644 --- a/chorus_lib/examples/loc-poly.rs +++ b/chorus_lib/examples/loc-poly.rs @@ -2,11 +2,9 @@ extern crate chorus_lib; use std::fmt::Debug; use std::thread; -use chorus_lib::core::{ - ChoreoOp, Choreography, ChoreographyLocation, Located, Portable, Projector, -}; +use chorus_lib::core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Portable}; use chorus_lib::transport::local::LocalTransport; -use chorus_lib::{hlist, projector}; +use chorus_lib::{projector, LocationSet}; #[derive(ChoreographyLocation)] struct Alice; @@ -27,7 +25,7 @@ where L1: ChoreographyLocation, L2: ChoreographyLocation, { - type L = hlist!(L1, L2); + type L = LocationSet!(L1, L2); fn run(self, op: &impl ChoreoOp) -> Located { let v = op.comm(self.sender, self.receiver, &self.data); op.locally(self.receiver, |un| println!("{:?}", un.unwrap(&v))); @@ -38,7 +36,7 @@ where struct MainChoreography; impl Choreography> for MainChoreography { - type L = hlist!(Alice, Bob); + type L = LocationSet!(Alice, Bob); fn run(self, op: &impl ChoreoOp) -> Located { let v1 = op.locally(Alice, |_| 100); @@ -58,15 +56,11 @@ impl Choreography> for MainChoreography { fn main() { let transport = LocalTransport::from(&[Alice::name(), Bob::name(), Carol::name()]); - - // Crate available locations for Projector - type AL = hlist!(Alice, Bob); - let mut handles = vec![]; { let transport = transport.clone(); handles.push(thread::spawn(|| { - let p = projector!(AL, Alice, transport); + let p = projector!(LocationSet!(Alice, Bob), Alice, transport); let v = p.epp_and_run(MainChoreography); assert_eq!(p.unwrap(v), 110); })); @@ -74,7 +68,7 @@ fn main() { { let transport = transport.clone(); handles.push(thread::spawn(|| { - let p = projector!(AL, Bob, transport); + let p = projector!(LocationSet!(Alice, Bob), Bob, transport); p.epp_and_run(MainChoreography); })); } diff --git a/chorus_lib/examples/runner.rs b/chorus_lib/examples/runner.rs index 29c9f55..83dd4a7 100644 --- a/chorus_lib/examples/runner.rs +++ b/chorus_lib/examples/runner.rs @@ -1,7 +1,7 @@ extern crate chorus_lib; use chorus_lib::{ core::{ChoreoOp, Choreography, ChoreographyLocation, Located, Runner, Superposition}, - hlist, + LocationSet, }; #[derive(ChoreographyLocation)] @@ -26,7 +26,7 @@ struct BobCarolChoreography { } impl Choreography for BobCarolChoreography { - type L = hlist!(Bob, Carol); + type L = LocationSet!(Bob, Carol); fn run(self, op: &impl ChoreoOp) -> BobCarolResult { let is_even_at_bob: Located = op.locally(Bob, |un| { let x = un.unwrap(&self.x_at_bob); @@ -50,7 +50,7 @@ impl Choreography for BobCarolChoreography { struct MainChoreography; impl Choreography for MainChoreography { - type L = hlist!(Alice, Bob, Carol); + type L = LocationSet!(Alice, Bob, Carol); fn run(self, op: &impl ChoreoOp) { let x_at_alice = op.locally(Alice, |_| get_random_number()); let x_at_bob = op.comm(Alice, Bob, &x_at_alice); diff --git a/chorus_lib/examples/tic-tac-toe.rs b/chorus_lib/examples/tic-tac-toe.rs index aae2dc8..a92da03 100644 --- a/chorus_lib/examples/tic-tac-toe.rs +++ b/chorus_lib/examples/tic-tac-toe.rs @@ -2,11 +2,10 @@ extern crate chorus_lib; use chorus_lib::{ - core::{ - ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, Projector, Serialize, - }, - hlist, projector, + core::{ChoreoOp, Choreography, ChoreographyLocation, Deserialize, Located, Serialize}, + projector, transport::http::HttpTransport, + LocationSet, }; use clap::Parser; use std::{collections::HashMap, io::Write}; @@ -228,7 +227,7 @@ struct TicTacToeChoreography { } impl Choreography for TicTacToeChoreography { - type L = hlist!(PlayerX, PlayerO); + type L = LocationSet!(PlayerX, PlayerO); fn run(self, op: &impl ChoreoOp) -> () { let mut board = Board::new(); loop { @@ -291,9 +290,6 @@ fn main() { Box::new(UserBrain::new(args.player)) }; - // Crate available locations for Projector - type AL = hlist!(PlayerX, PlayerO); - match args.player { 'X' => { let mut config = HashMap::new(); @@ -303,7 +299,7 @@ fn main() { (args.opponent_hostname.as_str(), args.opponent_port), ); let transport = HttpTransport::new(PlayerX::name(), &config); - let projector = projector!(AL, PlayerX, transport); + let projector = projector!(LocationSet!(PlayerX, PlayerO), PlayerX, transport); projector.epp_and_run(TicTacToeChoreography { brain_for_x: projector.local(brain), brain_for_o: projector.remote(PlayerO), @@ -317,7 +313,7 @@ fn main() { (args.opponent_hostname.as_str(), args.opponent_port), ); let transport = HttpTransport::new(PlayerO::name(), &config); - let projector = projector!(AL, PlayerO, transport); + let projector = projector!(LocationSet!(PlayerX, PlayerO), PlayerO, transport); projector.epp_and_run(TicTacToeChoreography { brain_for_x: projector.remote(PlayerX), brain_for_o: projector.local(brain), diff --git a/chorus_lib/src/core.rs b/chorus_lib/src/core.rs index 3f44deb..d59bf41 100644 --- a/chorus_lib/src/core.rs +++ b/chorus_lib/src/core.rs @@ -122,10 +122,10 @@ where /// Macro to generate hlist #[macro_export] -macro_rules! hlist { +macro_rules! LocationSet { () => { $crate::core::HNil }; ($head:ty $(,)*) => { $crate::core::HCons<$head, $crate::core::HNil> }; - ($head:ty, $($tail:tt)*) => { $crate::core::HCons<$head, hlist!($($tail)*)> }; + ($head:ty, $($tail:tt)*) => { $crate::core::HCons<$head, LocationSet!($($tail)*)> }; } /// Marker @@ -271,13 +271,13 @@ pub trait Transport { } /// Provides a method to perform end-point projection. -pub struct Projector +pub struct Projector where - L1: Member, + L1: Member, { target: PhantomData, transport: T, - available_locations: PhantomData, + location_set: PhantomData, index: PhantomData, } @@ -285,13 +285,13 @@ where #[macro_export] macro_rules! projector { ($al_type:ty, $target:expr, $transport:expr) => { - Projector::<$al_type, _, _, _>::new($target, $transport) + $crate::core::Projector::<$al_type, _, _, _>::new($target, $transport) }; } -impl Projector +impl Projector where - L1: Member, + L1: Member, { /// Constructs a `Projector` struct. /// @@ -301,7 +301,7 @@ where Projector { target: PhantomData, transport, - available_locations: PhantomData, + location_set: PhantomData, index: PhantomData, } } @@ -318,7 +318,7 @@ where /// Use this method to run a choreography that takes a located value as an input. pub fn remote(&self, _l2: L2) -> Located where - L2: Member<>::Remainder, Index2>, + L2: Member<>::Remainder, Index2>, { Located::remote() } @@ -336,7 +336,7 @@ where choreo: C, ) -> V where - L: Subset, + L: Subset, { struct EppOp<'a, L: HList, L1: ChoreographyLocation, B: Transport> { target: PhantomData, From 07730daf8592710121323d40a20bc172a3c14231 Mon Sep 17 00:00:00 2001 From: Soroush Zare Date: Sat, 16 Sep 2023 18:51:54 -0700 Subject: [PATCH 11/11] Update projector guide --- chorus_book/src/guide-projector.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chorus_book/src/guide-projector.md b/chorus_book/src/guide-projector.md index 8b32821..d8abf63 100644 --- a/chorus_book/src/guide-projector.md +++ b/chorus_book/src/guide-projector.md @@ -4,7 +4,7 @@ Projector is responsible for performing the end-point projection and executing t ## Creating a Projector -To create a `Projector`, you need to provide the set of locations it can work with, the target location, and the transport. +To create a `Projector`, you need to provide the set of locations it can work with, the target location, and the transport. You should use the `projector!` macro instead of directly instantiating a Projector. ```rust # extern crate chorus_lib; @@ -21,7 +21,7 @@ To create a `Projector`, you need to provide the set of locations it can work wi let projector = projector!(LocationSet!(Alice, Bob), Alice, transport); ``` -Notice that the `Projector` is parameterized by the location type. You will need one projector for each location to execute choreography. +Notice that the `Projector` is parameterized by its target location type. You will need one projector for each location to execute choreography. ## Executing a Choreography