Skip to content

Commit

Permalink
Merge pull request #1239 from Barsik-sus/wca_re_work_help_generation
Browse files Browse the repository at this point in the history
READY: (wca): Re-work help generation and removing unsafe code
  • Loading branch information
Wandalen authored Mar 25, 2024
2 parents ec6dec1 + 8999fd2 commit cda4ab9
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 212 deletions.
5 changes: 0 additions & 5 deletions module/move/wca/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ The tool to make CLI ( commands user interface ). It is able to aggregate extern
.property( "property" ).hint( "simple property" ).kind( Type::String ).optional( true ).end()
.routine( | args : Args, props | { println!( "= Args\n{args:?}\n\n= Properties\n{props:?}\n" ) } )
.end()
.command( "inc" )
.hint( "This command increments a state number each time it is called consecutively. (E.g. `.inc .inc`)" )
.routine( | ctx : Context | { let i : &mut i32 = ctx.get_or_default(); println!( "i = {i}" ); *i += 1; } )
.end()
.command( "error" )
.hint( "prints all subjects and properties" )
.subject().hint( "Error message" ).kind( Type::String ).optional( true ).end()
Expand Down Expand Up @@ -63,4 +59,3 @@ cd wTools
cd examples/wca_trivial
cargo run
```

9 changes: 8 additions & 1 deletion module/move/wca/examples/wca_fluent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use wca::{ Args, Context, Type };
use std::sync::{ Arc, Mutex };

fn main()
{
Expand All @@ -21,7 +22,13 @@ fn main()
.end()
.command( "inc" )
.hint( "This command increments a state number each time it is called consecutively. (E.g. `.inc .inc`)" )
.routine( | ctx : Context | { let i : &mut i32 = ctx.get_or_default(); println!( "i = {i}" ); *i += 1; } )
.routine( | ctx : Context |
{
let i : Arc< Mutex< i32 > > = ctx.get_or_default();
let mut i = i.lock().unwrap();
println!( "i = {}", i );
*i += 1;
} )
.end()
.command( "error" )
.hint( "prints all subjects and properties" )
Expand Down
23 changes: 14 additions & 9 deletions module/move/wca/src/ca/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub( crate ) mod private
ProgramParser,
Command,
grammar::command::private::CommandFormer,
help::{ HelpGeneratorFn, HelpVariants, dot_command },
help::{ HelpGeneratorFn, HelpGeneratorArgs, HelpVariants, dot_command },
};

use std::collections::HashSet;
Expand All @@ -20,6 +20,7 @@ pub( crate ) mod private
for_app::Error as wError,
for_lib::*,
};
use wtools::Itertools;

/// Validation errors that can occur in application.
#[ derive( Error, Debug ) ]
Expand Down Expand Up @@ -107,11 +108,12 @@ pub( crate ) mod private
#[ default( Executor::former().form() ) ]
executor : Executor,

help_generator : HelpGeneratorFn,
help_generator : Option< HelpGeneratorFn >,
#[ default( HashSet::from([ HelpVariants::All ]) ) ]
help_variants : HashSet< HelpVariants >,
// qqq : for Bohdan : should not have fields help_generator and help_variants
// aaa : for Bohdan : should not have fields help_generator and help_variants
// help_generator generateds VerifiedCommand(s) and stop to exist
// aaa : Defaults after formation

// #[ default( Verifier::former().form() ) ]
#[ default( Verifier ) ]
Expand Down Expand Up @@ -200,7 +202,7 @@ pub( crate ) mod private
/// ```
pub fn help< HelpFunction >( mut self, func : HelpFunction ) -> Self
where
HelpFunction : Fn( &Dictionary, Option< &Command > ) -> String + 'static
HelpFunction : Fn( &Dictionary, HelpGeneratorArgs< '_ > ) -> String + 'static
{
self.storage.help_generator = Some( HelpGeneratorFn::new( func ) );
self
Expand Down Expand Up @@ -238,19 +240,22 @@ pub( crate ) mod private
{
let mut ca = self;

if ca.help_variants.contains( &HelpVariants::All )
let help_generator = std::mem::take( &mut ca.help_generator ).unwrap_or_default();
let help_variants = std::mem::take( &mut ca.help_variants );

if help_variants.contains( &HelpVariants::All )
{
HelpVariants::All.generate( &ca.help_generator, &mut ca.dictionary );
HelpVariants::All.generate( &help_generator, &mut ca.dictionary );
}
else
{
for help in &ca.help_variants
for help in help_variants.iter().sorted()
{
help.generate( &ca.help_generator, &mut ca.dictionary );
help.generate( &help_generator, &mut ca.dictionary );
}
}

dot_command( &mut ca.dictionary );
dot_command( &help_generator, &mut ca.dictionary );

ca
}
Expand Down
42 changes: 17 additions & 25 deletions module/move/wca/src/ca/executor/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,10 @@ pub( crate ) mod private
/// Initialize Context with some value
pub fn with< T : CloneAny >( mut self, value : T ) -> Self
{
if self.storage.inner.is_none()
{
self.storage.inner = Some( Arc::new( RefCell::new( Map::< dyn CloneAny >::new() ) ) );
}
self.storage.inner.as_ref().map( | inner | inner.borrow_mut().insert( value ) );
let inner = self.storage.inner.unwrap_or_else( || Context::default().inner );
inner.borrow_mut().insert( value );

self.storage.inner = Some( inner );
self
}
}
Expand All @@ -81,46 +80,39 @@ pub( crate ) mod private
self.inner.borrow_mut().remove::< T >()
}

// qqq : Bohdan : why unsafe?
/// Return immutable reference on interior object. ! Unsafe !
pub fn get_ref< T : CloneAny >( &self ) -> Option< &T >
{
unsafe{ self.inner.as_ptr().as_ref()?.get() }
}
// aaa : Bohdan : why unsafe?
// aaa : re-worked.

/// Return mutable reference on interior object. ! Unsafe !
pub fn get_mut< T : CloneAny >( &self ) -> Option< &mut T >
/// Return immutable reference on interior object.
pub fn get< T : CloneAny + Clone >( &self ) -> Option< T >
{
unsafe { self.inner.as_ptr().as_mut()?.get_mut() }
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 >( &self, value : T ) -> &mut T
pub fn get_or_insert< T : CloneAny + Clone >( &self, value : T ) -> T
{
if let Some( value ) = self.get_mut()
if let Some( value ) = self.get()
{
value
}
else
{
self.insert( value );
self.get_mut().unwrap()
self.get().unwrap()
}
}

/// 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 >( &self ) -> &mut T
pub fn get_or_default< T : CloneAny + Default + Clone >( &self ) -> T
{
self.get_or_insert( T::default() )
}

/// Make a deep clone of the context
// qqq : for Bohdan : why is it deep? how is it deep?
// qqq : how is it useful? Is it? Examples?
pub( crate ) fn deep_clone( &self ) -> Self
{
Self { inner : Arc::new( RefCell::new( ( *self.inner ).borrow_mut().clone() ) ) }
}
// aaa : for Bohdan : why is it deep? how is it deep?
// aaa : how is it useful? Is it? Examples?
//
// aaa : removed
}
}

Expand Down
91 changes: 0 additions & 91 deletions module/move/wca/src/ca/executor/converter.rs
Original file line number Diff line number Diff line change
@@ -1,91 +0,0 @@
pub( crate ) mod private
{
use crate::*;
use former::Former;
use std::collections::HashMap;
use wtools::{ error::Result, err };

/// This is the struct that provides a way to convert a `VerifiedCommand` to an `ExecutableCommand_`.
///
/// The conversion is done by looking up the `Routine` associated with the command in a HashMap of routines.
///
/// ```
/// # use wca::{ Command, Type, VerifiedCommand, ExecutorConverter, Routine };
/// # use std::collections::HashMap;
/// # fn main() -> Result< (), Box< dyn std::error::Error > > {
/// let executor_converter = ExecutorConverter::former()
/// .routine( "command", Routine::new( |( args, props )| Ok( () ) ) )
/// .form();
///
/// let grammar_command = VerifiedCommand
/// {
/// phrase : "command".to_string(),
/// subjects : vec![],
/// properties : HashMap::new(),
/// };
///
/// let executable_command = executor_converter.to_command( grammar_command )?;
/// # Ok( () ) }
/// ```
#[ derive( Debug ) ]
#[ derive( Former ) ]
pub struct ExecutorConverter
{
pub( crate ) routines : HashMap< String, Routine >,
}

impl ExecutorConverterFormer
{
/// Inserts routine to a routine dictionary
pub fn routine< S >( mut self, phrase : S, routine : Routine ) -> Self
where
S : Into< String >,
Routine : Into< Routine >,
{
let mut routines = self.storage.routines.unwrap_or_default();

routines.insert( phrase.into(), routine );

self.storage.routines = Some( routines );
self
}
}

impl ExecutorConverter
{
/// Converts raw program to executable
pub fn to_program( &self, raw_program : Program< VerifiedCommand > ) -> Result< Program< ExecutableCommand_ > >
{
let commands = raw_program.commands
.into_iter()
.map( | n | self.to_command( n ) )
.collect::< Result< Vec< ExecutableCommand_ > > >()?;

Ok( Program { commands } )
}

/// Converts raw command to executable
pub fn to_command( &self, command : VerifiedCommand ) -> Result< ExecutableCommand_ >
{
self.routines
.get( &command.phrase )
.ok_or_else( || err!( "Can not found routine for command `{}`", command.phrase ) )
.map
(
| routine | ExecutableCommand_
{
subjects : command.subjects,
properties : command.properties,
routine : routine.clone(),
}
)
}
}
}

//

crate::mod_interface!
{
exposed use ExecutorConverter;
}
8 changes: 5 additions & 3 deletions module/move/wca/src/ca/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub( crate ) mod private

use ca::executor::runtime::_exec_command;
use wtools::error::Result;
use std::sync::Arc;
use std::sync::atomic::Ordering;

// aaa : for Bohdan : how is it useful? where is it used?
// aaa : `ExecutorType` has been removed
Expand Down Expand Up @@ -55,10 +57,10 @@ pub( crate ) mod private
{
while !runtime.is_finished()
{
let state = runtime.context.get_or_default::< RuntimeState >();
state.pos = runtime.pos + 1;
let state = runtime.context.get_or_default::< Arc< RuntimeState > >();
state.pos.store( runtime.pos + 1, Ordering::Release );
runtime.r#do( &dictionary )?;
runtime.pos = runtime.context.get_ref::< RuntimeState >().unwrap().pos;
runtime.pos = runtime.context.get::< Arc< RuntimeState > >().unwrap().pos.load( Ordering::Relaxed );
}

Ok( () )
Expand Down
4 changes: 0 additions & 4 deletions module/move/wca/src/ca/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ crate::mod_interface!
layer executor;
/// Represents the state of the program's runtime
layer runtime;
// /// Converts from `VerifiedCommand` to `ExecutableCommand_`
// layer converter;
/// Container for contexts values
layer context;
// /// `ExecutableCommand_` representation
// layer command;
/// Command callback representation
layer routine;

Expand Down
4 changes: 3 additions & 1 deletion module/move/wca/src/ca/executor/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ pub( crate ) mod private
{
use crate::*;
use wtools::{ error::Result, err };
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;

/// State of a program runtime
///
Expand All @@ -24,7 +26,7 @@ pub( crate ) mod private
pub struct RuntimeState
{
/// current execution position that can be changed by user
pub pos : usize,
pub pos : Arc< AtomicUsize >,
}
// qqq : for Bohdan : why? how is it useful? is it?

Expand Down
Loading

0 comments on commit cda4ab9

Please sign in to comment.