Skip to content

Commit

Permalink
Merge pull request #1274 from Barsik-sus/wca_context_re_work
Browse files Browse the repository at this point in the history
READY : (wca): Refactor Context Handling in `CommandsAggregator` and `Context`
  • Loading branch information
Wandalen authored Apr 1, 2024
2 parents 8c52ccc + 9875217 commit 99a5427
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 109 deletions.
3 changes: 1 addition & 2 deletions module/move/wca/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,9 @@ iter_tools = { workspace = true, features = [ "default" ] }
former = { workspace = true, features = [ "default" ] }

## external
anymap = "0.12"
log = "0.4"
nom = "7.1"
closure = "0.3"
#closure = "0.3"
eddie = { version = "0.4", optional = true } # fuzzy commands search

[dev-dependencies]
Expand Down
3 changes: 2 additions & 1 deletion module/move/wca/examples/wca_fluent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ fn main()
{

let ca = wca::CommandsAggregator::former()
.with_context( Mutex::new( 0 ) )
.command( "echo" )
.hint( "prints all subjects and properties" )
.subject().kind( Type::String ).optional( true ).end()
Expand All @@ -24,7 +25,7 @@ fn main()
.hint( "This command increments a state number each time it is called consecutively. (E.g. `.inc .inc`)" )
.routine( | ctx : Context |
{
let i : Arc< Mutex< i32 > > = ctx.get_or_default();
let i : Arc< Mutex< i32 > > = ctx.get().unwrap();
let mut i = i.lock().unwrap();
println!( "i = {}", i );
*i += 1;
Expand Down
51 changes: 22 additions & 29 deletions module/move/wca/src/ca/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,35 +156,28 @@ pub( crate ) mod private

impl CommandsAggregatorFormer
{
// qqq : delete on completion
// /// Setter for grammar
// ///
// /// Gets list of available commands
// pub fn grammar< V >( mut self, commands : V ) -> Self
// where
// V : Into< Vec< Command > >
// {
// let verifier = Verifier::former()
// .commands( commands )
// .form();
// self.storage.verifier = Some( verifier );
// self
// }

// /// Setter for executor
// ///
// /// Gets dictionary of routines( command name -> callback )
// pub fn executor< H >( mut self, routines : H ) -> Self
// where
// H : Into< HashMap< String, Routine > >
// {
// let executor = ExecutorConverter::former()
// .routines( routines )
// .form();
//
// self.storage.executor_converter = Some( executor );
// self
// }
/// Adds a context to the executor.
///
/// # Arguments
///
/// * `value` - The value to be used as the context.
///
/// # Returns
///
/// The modified instance of `Self`.
// `'static` means that the value must be owned or live at least as a `Context'
pub fn with_context< T >( mut self, value : T ) -> Self
where
T : Sync + Send + 'static,
{
let mut executor = self.storage.executor.unwrap_or_else( || Executor::former().form() );

executor.context = Context::new( value );

self.storage.executor = Some( executor );

self
}

/// Setter for help content generator
///
Expand Down
111 changes: 38 additions & 73 deletions module/move/wca/src/ca/executor/context.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,25 @@
pub( crate ) mod private
{
use std::{ sync::Arc, cell::RefCell };
use anymap::{ Map, any::CloneAny };
use std::sync::Arc;

/// Container for contexts values
///
/// # Examples:
///
/// ```
/// use wca::Context;
///
/// let ctx = Context::default();
///
/// ctx.insert( 42 );
/// assert_eq!( 42, ctx.get().unwrap() );
/// ```
///
/// ```
/// # use wca::{ Routine, Handler, Context, Value, Args, Props, VerifiedCommand };
/// # use std::sync::{ Arc, Mutex };
/// let routine = Routine::from( Handler::from
/// (
/// | ctx : Context, o : VerifiedCommand |
/// {
/// let first_arg : i32 = o.args.get_owned( 0 ).unwrap_or_default();
/// let ctx_value : Arc< Mutex< i32 > > = ctx.get_or_default();
/// let ctx_value : Arc< Mutex< i32 > > = ctx.get().unwrap();
///
/// *ctx_value.lock().unwrap() += first_arg;
/// }
/// ) );
/// let ctx = Context::default();
/// let ctx = Context::new( Mutex::new( 0 ) );
/// if let Routine::WithContext( callback ) = routine
/// {
/// let w_command = VerifiedCommand
Expand All @@ -41,84 +31,59 @@ pub( crate ) mod private
/// };
/// callback( ctx.clone(), w_command ).unwrap();
/// }
/// assert_eq!( 1, *ctx.get::< Arc< Mutex< i32 > > >().unwrap().lock().unwrap() );
/// assert_eq!( 1, *ctx.get::< Mutex< i32 > >().unwrap().lock().unwrap() );
/// ```
// CloneAny needs to deep clone of Context
// qqq : ?
#[ derive( Debug, Clone, former::Former ) ]
#[ derive( Debug, Clone ) ]
pub struct Context
{
inner : Arc< RefCell< Map::< dyn CloneAny > > >
}

impl ContextFormer
{
/// Initialize Context with some value
pub fn with< T : CloneAny >( mut self, value : T ) -> Self
{
let inner = self.storage.inner.unwrap_or_else( || Context::default().inner );
inner.borrow_mut().insert( value );

self.storage.inner = Some( inner );
self
}
inner : Arc< dyn std::any::Any + Send + Sync >,
}

impl Default for Context
{
fn default() -> Self
{
Self { inner : Arc::new( RefCell::new( Map::< dyn CloneAny >::new() ) ) }
Self::new( () )
}
}

impl Context
{
/// Insert the T value to the context. If it is already exists - replace it
pub fn insert< T : CloneAny >( &self, value : T )
{
self.inner.borrow_mut().insert( value );
}

/// Removes the T value from the context
pub fn remove< T : CloneAny >( &mut self ) -> Option< T >
{
self.inner.borrow_mut().remove::< T >()
}

// aaa : Bohdan : why unsafe?
// aaa : re-worked.

/// Return immutable reference on interior object.
pub fn get< T : CloneAny + Clone >( &self ) -> Option< T >
/// Creates a new `Context` object with the given value.
///
/// # Arguments
///
/// * `value` - The value to be stored in the `Context`. The value must implement the `Send` and `Sync` traits.
/// ```
// `'static` means that the object must be owned or live at least as a `Context'
pub fn new< T : Send + Sync + 'static >( value : T ) -> Self
{
self.inner.borrow().get().cloned()
}

/// Insert the value if it doesn't exists, or take an existing value and return mutable reference to it
pub fn get_or_insert< T : CloneAny + Clone >( &self, value : T ) -> T
{
if let Some( value ) = self.get()
{
value
}
else
{
self.insert( value );
self.get().unwrap()
}
Self { inner : Arc::new( value ) }
}
}

/// Insert default value if it doesn't exists, or take an existing value and return mutable reference to it
pub fn get_or_default< T : CloneAny + Default + Clone >( &self ) -> T
impl Context
{
/// This method retrieves a shared reference to an object of type `T` from the context.
///
/// # Arguments
///
/// * `&self` - The context object.
///
/// # Type Parameters
///
/// * `T` - The type of the object to retrieve.
///
/// # Returns
///
/// An `Option` containing a reference-counted smart pointer (`Arc`) to the object of type `T` if it exists in the context.
/// `None` is returned if the object does not exist or if it cannot be downcasted to type `T`.
// `'static` means that the object must be owned or live at least as a `Context'
pub fn get< T : Send + Sync + 'static >( &self ) -> Option< Arc< T > >
{
self.get_or_insert( T::default() )
self.inner.clone().downcast::< T >().ok()
}

// aaa : for Bohdan : why is it deep? how is it deep?
// aaa : how is it useful? Is it? Examples?
//
// aaa : removed
}
}

Expand Down
3 changes: 1 addition & 2 deletions module/move/wca/tests/inc/executor/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ tests_impls!
)
.form();
let verifier = Verifier;
let mut ctx = wca::Context::default();
ctx.insert( Arc::new( Mutex::new( 1 ) ) );
let mut ctx = wca::Context::new( Mutex::new( 1 ) );
// init executor
let executor = Executor::former()
.context( ctx )
Expand Down
3 changes: 1 addition & 2 deletions module/move/wca/tests/inc/executor/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ tests_impls!
let verifier = Verifier;

// starts with 0
let mut ctx = wca::Context::default();
ctx.insert( Arc::new( Mutex::new( 0 ) ) );
let ctx = wca::Context::new( Mutex::new( 0 ) );
// init simple executor
let executor = Executor::former()
.context( ctx )
Expand Down

0 comments on commit 99a5427

Please sign in to comment.