1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
pub( crate ) mod private
{
use crate::
{
Program, Namespace,
GrammarCommand, ExecutableCommand,
Routine, wtools,
};
use former::Former;
use std::collections::HashMap;
use wtools::{ error::Result, err };
/// This is the struct that provides a way to convert a `GrammarCommand` 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, GrammarCommand, 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 = GrammarCommand
/// {
/// 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.routines.unwrap_or_default();
routines.insert( phrase.into(), routine );
self.routines = Some( routines );
self
}
}
impl ExecutorConverter
{
/// Converts raw program to executable
pub fn to_program( &self, raw_program : Program< Namespace< GrammarCommand > > ) -> Result< Program< Namespace< ExecutableCommand > > >
{
let namespaces = raw_program.namespaces
.into_iter()
.map( | n | self.to_namespace( n ) )
.collect::< Result< Vec< Namespace< ExecutableCommand > > > >()?;
Ok( Program { namespaces } )
}
/// Converts raw namespace to executable
pub fn to_namespace( &self, raw_namespace : Namespace< GrammarCommand > ) -> Result< Namespace< ExecutableCommand > >
{
let commands = raw_namespace.commands
.into_iter()
.map( | c | self.to_command( c ) )
.collect::< Result< Vec< ExecutableCommand > > >()?;
Ok( Namespace { commands } )
}
/// Converts raw command to executable
pub fn to_command( &self, command : GrammarCommand ) -> 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!
{
prelude use ExecutorConverter;
}