Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::env;
- use num_traits::Float;
- use std::str::FromStr;
- use std::fmt::Debug;
- use std::collections::HashMap;
- // Basic Stack is just a vector
- struct Stack< T >
- {
- stack: Vec< T >,
- }
- // Implementation provides push, pop, pick etc
- impl< T : Copy > Stack< T >
- {
- fn new( ) -> Self
- {
- Stack { stack: Vec::new( ) }
- }
- fn depth( &self ) -> usize
- {
- self.stack.len( )
- }
- fn pop( &mut self ) -> Option< T >
- {
- self.stack.pop( )
- }
- fn push( &mut self, item: T )
- {
- self.stack.push( item );
- }
- fn pick( &self, index: usize ) -> T
- {
- let depth = self.depth( );
- self.stack[ depth - index - 1 ]
- }
- }
- // For now, only Floats types are supported
- trait StackEntry : Float + FromStr + Debug
- {
- }
- // This ensures the f32 and f64 are identified as StackEntry
- impl< T : Float + FromStr + Debug > StackEntry for T
- {
- }
- // Vocab implementation
- fn add< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- let bos = stack.pop( );
- stack.push( bos.unwrap( ) + tos.unwrap( ) );
- }
- fn sub< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- let bos = stack.pop( );
- stack.push( bos.unwrap( ) - tos.unwrap( ) );
- }
- fn mul< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- let bos = stack.pop( );
- stack.push( bos.unwrap( ) * tos.unwrap( ) );
- }
- fn div< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- let bos = stack.pop( );
- stack.push( bos.unwrap( ) / tos.unwrap( ) );
- }
- fn dup< T : StackEntry >( stack: &mut Stack< T > )
- {
- let value = stack.pick( 0 );
- stack.push( value );
- }
- fn drop< T : StackEntry >( stack: &mut Stack< T > )
- {
- stack.pop( );
- }
- fn dot< T : StackEntry >( stack: &mut Stack< T > )
- {
- let result = stack.pop( );
- match result
- {
- Some( x ) => println!( "{:?}", x ),
- None => println!( "ERR: Underflow" ),
- };
- }
- struct Vocabulary< T >
- {
- list : HashMap< String, fn( stack: &mut Stack< T > ) >,
- }
- impl< T : StackEntry > Vocabulary< T >
- {
- fn new( ) -> Self
- {
- Vocabulary { list: HashMap::new( ) }
- }
- fn add( &mut self, name: &str, func: fn( stack: &mut Stack< T > ) )
- {
- self.list.insert( name.to_string( ), func );
- }
- fn eval( &self, stack: &mut Stack< T >, token: String )
- {
- match self.list.get( token.as_str( ) )
- {
- Some( word ) => word( stack ),
- _ => stack.push( token.as_str( ).parse::< T >( ).unwrap_or( T::nan( ) ) ),
- }
- }
- }
- fn run< T : StackEntry >( )
- {
- let mut stack: Stack< T > = Stack::new( );
- let mut vocab: Vocabulary< T > = Vocabulary::new( );
- vocab.add( "+", add );
- vocab.add( "-", sub );
- vocab.add( "*", mul );
- vocab.add( "/", div );
- vocab.add( ".", dot );
- vocab.add( "drop", drop );
- vocab.add( "dup", dup );
- let args: Vec< String > = env::args( ).collect( );
- for arg in args.iter( ).skip( 1 )
- {
- vocab.eval( &mut stack, arg.to_string( ) );
- }
- if stack.depth( ) > 0
- {
- dot( &mut stack );
- }
- }
- fn main( )
- {
- run::< f32 >( );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement