Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::env;
- use num_traits::Float;
- use num_traits::FloatConst;
- use std::str::FromStr;
- use std::fmt::Debug;
- use std::collections::HashMap;
- // For now, only Floats types are supported
- trait StackEntry : FloatConst + Float + FromStr + Debug
- {
- }
- // This ensures the f32 and f64 are identified as StackEntry
- impl< T : FloatConst + Float + FromStr + Debug > StackEntry for T
- {
- }
- // A stack contains its data and a dictionary
- struct Stack< T >
- {
- data: Vec< T >,
- dict: HashMap< String, fn( stack: &mut Stack< T > ) >,
- }
- // Implementation of a stack
- impl< T : StackEntry > Stack< T >
- {
- fn new( ) -> Self
- {
- Stack { data: Vec::new( ), dict: HashMap::new( ) }
- }
- fn add( &mut self, name: &str, func: fn( stack: &mut Stack< T > ) )
- {
- self.dict.insert( name.to_string( ), func );
- }
- fn eval( &mut self, token: String )
- {
- match self.dict.get( token.as_str( ) )
- {
- Some( word ) => word( self ),
- _ => self.data.push( token.as_str( ).parse::< T >( ).unwrap_or( T::nan( ) ) ),
- }
- }
- fn depth( &self ) -> usize
- {
- self.data.len( )
- }
- fn pop( &mut self ) -> Option< T >
- {
- self.data.pop( )
- }
- fn push( &mut self, item: T )
- {
- self.data.push( item );
- }
- fn pick( &self, index: usize ) -> T
- {
- let depth = self.depth( );
- self.data[ depth - index - 1 ]
- }
- }
- // Basic arithmetic operations
- 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 modulo< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- let bos = stack.pop( );
- stack.push( bos.unwrap( ) % tos.unwrap( ) );
- }
- // Maths
- fn neg< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( - tos.unwrap( ) );
- }
- fn floor< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).floor( ) );
- }
- fn ceil< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).ceil( ) );
- }
- fn round< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).round( ) );
- }
- fn trunc< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).trunc( ) );
- }
- fn fract< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).fract( ) );
- }
- fn abs< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).abs( ) );
- }
- fn signum< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).signum( ) );
- }
- fn pow< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- let bos = stack.pop( );
- stack.push( T::powf( bos.unwrap( ), tos.unwrap( ) ) );
- }
- fn sqrt< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- stack.push( tos.unwrap( ).sqrt( ) );
- }
- fn e< T : StackEntry >( stack: &mut Stack< T > ) { stack.push( T::E( ) ); }
- fn pi< T : StackEntry >( stack: &mut Stack< T > ) { stack.push( T::PI( ) ); }
- // Unusual rust specific stuff
- fn mul_add< T : StackEntry >( stack: &mut Stack< T > )
- {
- let tos = stack.pop( );
- let mos = stack.pop( );
- let bos = stack.pop( );
- stack.push( bos.unwrap( ).mul_add( mos.unwrap( ), tos.unwrap( ) ) );
- }
- // Stack manipulations
- 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( );
- }
- // Output
- fn dot< T : StackEntry >( stack: &mut Stack< T > )
- {
- let result = stack.pop( );
- match result
- {
- Some( x ) => println!( "{:?}", x ),
- None => println!( "ERR: Underflow" ),
- };
- }
- // Help
- fn help< T : StackEntry >( stack: &mut Stack< T > )
- {
- for key in stack.dict.keys( )
- {
- print!( "{} ", key );
- }
- println!( "" );
- }
- // Evaluates command line arguments
- fn run< T : StackEntry >( )
- {
- let mut stack: Stack< T > = Stack::new( );
- stack.add( "+", add );
- stack.add( "-", sub );
- stack.add( "*", mul );
- stack.add( "/", div );
- stack.add( "%", modulo );
- stack.add( "neg", neg );
- stack.add( "floor", floor );
- stack.add( "ceil", ceil );
- stack.add( "round", round );
- stack.add( "trunc", trunc );
- stack.add( "fract", fract );
- stack.add( "abs", abs );
- stack.add( "signum", signum );
- stack.add( "sqrt", sqrt );
- stack.add( "**", pow );
- stack.add( "e", e );
- stack.add( "pi", pi );
- stack.add( "mul_add", mul_add );
- stack.add( "drop", drop );
- stack.add( "dup", dup );
- stack.add( ".", dot );
- stack.add( "help", help );
- let args: Vec< String > = env::args( ).collect( );
- for arg in args.iter( ).skip( 1 )
- {
- stack.eval( arg.to_string( ) );
- }
- if stack.depth( ) > 0
- {
- dot( &mut stack );
- }
- }
- fn main( )
- {
- run::< f32 >( );
- }
Add Comment
Please, Sign In to add comment