lilo_booter

rrpn v3

Mar 30th, 2022 (edited)
638
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.32 KB | None | 0 0
  1. use std::env;
  2. use num_traits::Float;
  3. use num_traits::FloatConst;
  4. use std::str::FromStr;
  5. use std::fmt::Debug;
  6. use std::collections::HashMap;
  7.  
  8. // For now, only Floats types are supported
  9. trait StackEntry : FloatConst + Float + FromStr + Debug
  10. {
  11. }
  12.  
  13. // This ensures the f32 and f64 are identified as StackEntry
  14. impl< T : FloatConst + Float + FromStr + Debug > StackEntry for T
  15. {
  16. }
  17.  
  18. // A stack contains its data and a dictionary
  19. struct Stack< T >
  20. {
  21.     data: Vec< T >,
  22.     dict: HashMap< String, fn( stack: &mut Stack< T > ) >,
  23. }
  24.  
  25. // Implementation of a stack
  26. impl< T : StackEntry > Stack< T >
  27. {
  28.     fn new( ) -> Self
  29.     {
  30.         Stack { data: Vec::new( ), dict: HashMap::new( ) }
  31.     }
  32.  
  33.     fn add( &mut self, name: &str, func: fn( stack: &mut Stack< T > ) )
  34.     {
  35.         self.dict.insert( name.to_string( ), func );
  36.     }
  37.  
  38.     fn eval( &mut self, token: String )
  39.     {
  40.         match self.dict.get( token.as_str( ) )
  41.         {
  42.             Some( word ) => word( self ),
  43.             _ => self.data.push( token.as_str( ).parse::< T >( ).unwrap_or( T::nan( ) ) ),
  44.         }
  45.     }
  46.  
  47.     fn depth( &self ) -> usize
  48.     {
  49.         self.data.len( )
  50.     }
  51.  
  52.     fn pop( &mut self ) -> Option< T >
  53.     {
  54.         self.data.pop( )
  55.     }
  56.  
  57.     fn push( &mut self, item: T )
  58.     {
  59.         self.data.push( item );
  60.     }
  61.  
  62.     fn pick( &self, index: usize ) -> T
  63.     {
  64.         let depth = self.depth( );
  65.         self.data[ depth - index - 1 ]
  66.     }
  67. }
  68.  
  69. // Basic arithmetic operations
  70. fn add< T : StackEntry >( stack: &mut Stack< T > )
  71. {
  72.     let tos = stack.pop( );
  73.     let bos = stack.pop( );
  74.     stack.push( bos.unwrap( ) + tos.unwrap( ) );
  75. }
  76.  
  77. fn sub< T : StackEntry >( stack: &mut Stack< T > )
  78. {
  79.     let tos = stack.pop( );
  80.     let bos = stack.pop( );
  81.     stack.push( bos.unwrap( ) - tos.unwrap( ) );
  82. }
  83.  
  84. fn mul< T : StackEntry >( stack: &mut Stack< T > )
  85. {
  86.     let tos = stack.pop( );
  87.     let bos = stack.pop( );
  88.     stack.push( bos.unwrap( ) * tos.unwrap( ) );
  89. }
  90.  
  91. fn div< T : StackEntry >( stack: &mut Stack< T > )
  92. {
  93.     let tos = stack.pop( );
  94.     let bos = stack.pop( );
  95.     stack.push( bos.unwrap( ) / tos.unwrap( ) );
  96. }
  97.  
  98. fn modulo< T : StackEntry >( stack: &mut Stack< T > )
  99. {
  100.     let tos = stack.pop( );
  101.     let bos = stack.pop( );
  102.     stack.push( bos.unwrap( ) % tos.unwrap( ) );
  103. }
  104.  
  105. // Maths
  106. fn neg< T : StackEntry >( stack: &mut Stack< T > )
  107. {
  108.     let tos = stack.pop( );
  109.     stack.push( - tos.unwrap( ) );
  110. }
  111.  
  112. fn floor< T : StackEntry >( stack: &mut Stack< T > )
  113. {
  114.     let tos = stack.pop( );
  115.     stack.push( tos.unwrap( ).floor( ) );
  116. }
  117.  
  118. fn ceil< T : StackEntry >( stack: &mut Stack< T > )
  119. {
  120.     let tos = stack.pop( );
  121.     stack.push( tos.unwrap( ).ceil( ) );
  122. }
  123.  
  124. fn round< T : StackEntry >( stack: &mut Stack< T > )
  125. {
  126.     let tos = stack.pop( );
  127.     stack.push( tos.unwrap( ).round( ) );
  128. }
  129.  
  130. fn trunc< T : StackEntry >( stack: &mut Stack< T > )
  131. {
  132.     let tos = stack.pop( );
  133.     stack.push( tos.unwrap( ).trunc( ) );
  134. }
  135.  
  136. fn fract< T : StackEntry >( stack: &mut Stack< T > )
  137. {
  138.     let tos = stack.pop( );
  139.     stack.push( tos.unwrap( ).fract( ) );
  140. }
  141.  
  142. fn abs< T : StackEntry >( stack: &mut Stack< T > )
  143. {
  144.     let tos = stack.pop( );
  145.     stack.push( tos.unwrap( ).abs( ) );
  146. }
  147.  
  148. fn signum< T : StackEntry >( stack: &mut Stack< T > )
  149. {
  150.     let tos = stack.pop( );
  151.     stack.push( tos.unwrap( ).signum( ) );
  152. }
  153.  
  154. fn pow< T : StackEntry >( stack: &mut Stack< T > )
  155. {
  156.     let tos = stack.pop( );
  157.     let bos = stack.pop( );
  158.     stack.push( T::powf( bos.unwrap( ), tos.unwrap( ) ) );
  159. }
  160.  
  161. fn sqrt< T : StackEntry >( stack: &mut Stack< T > )
  162. {
  163.     let tos = stack.pop( );
  164.     stack.push( tos.unwrap( ).sqrt( ) );
  165. }
  166.  
  167. fn e< T : StackEntry >( stack: &mut Stack< T > ) { stack.push( T::E( ) ); }
  168.  
  169. fn pi< T : StackEntry >( stack: &mut Stack< T > ) { stack.push( T::PI( ) ); }
  170.  
  171. // Unusual rust specific stuff
  172. fn mul_add< T : StackEntry >( stack: &mut Stack< T > )
  173. {
  174.     let tos = stack.pop( );
  175.     let mos = stack.pop( );
  176.     let bos = stack.pop( );
  177.     stack.push( bos.unwrap( ).mul_add( mos.unwrap( ), tos.unwrap( ) ) );
  178. }
  179.  
  180. // Stack manipulations
  181. fn dup< T : StackEntry >( stack: &mut Stack< T > )
  182. {
  183.     let value = stack.pick( 0 );
  184.     stack.push( value );
  185. }
  186.  
  187. fn drop< T : StackEntry >( stack: &mut Stack< T > )
  188. {
  189.     stack.pop( );
  190. }
  191.  
  192. // Output
  193. fn dot< T : StackEntry >( stack: &mut Stack< T > )
  194. {
  195.     let result = stack.pop( );
  196.     match result
  197.     {
  198.         Some( x ) => println!( "{:?}", x ),
  199.         None      => println!( "ERR: Underflow" ),
  200.     };
  201. }
  202.  
  203. // Help
  204. fn help< T : StackEntry >( stack: &mut Stack< T > )
  205. {
  206.     for key in stack.dict.keys( )
  207.     {
  208.         print!( "{} ", key );
  209.     }
  210.     println!( "" );
  211. }
  212.  
  213. // Evaluates command line arguments
  214. fn run< T : StackEntry >( )
  215. {
  216.     let mut stack: Stack< T > = Stack::new( );
  217.     stack.add( "+", add );
  218.     stack.add( "-", sub );
  219.     stack.add( "*", mul );
  220.     stack.add( "/", div );
  221.     stack.add( "%", modulo );
  222.  
  223.     stack.add( "neg", neg );
  224.     stack.add( "floor", floor );
  225.     stack.add( "ceil", ceil );
  226.     stack.add( "round", round );
  227.     stack.add( "trunc", trunc );
  228.     stack.add( "fract", fract );
  229.     stack.add( "abs", abs );
  230.     stack.add( "signum", signum );
  231.     stack.add( "sqrt", sqrt );
  232.     stack.add( "**", pow );
  233.     stack.add( "e", e );
  234.     stack.add( "pi", pi );
  235.  
  236.     stack.add( "mul_add", mul_add );
  237.  
  238.     stack.add( "drop", drop );
  239.     stack.add( "dup", dup );
  240.  
  241.     stack.add( ".", dot );
  242.  
  243.     stack.add( "help", help );
  244.  
  245.     let args: Vec< String > = env::args( ).collect( );
  246.     for arg in args.iter( ).skip( 1 )
  247.     {
  248.         stack.eval( arg.to_string( ) );
  249.     }
  250.  
  251.     if stack.depth( ) > 0
  252.     {
  253.         dot( &mut stack );
  254.     }
  255. }
  256.  
  257. fn main( )
  258. {
  259.     run::< f32 >( );
  260. }
  261.  
Add Comment
Please, Sign In to add comment