Advertisement
Ponser

Forth interpreter in Rust

Jul 7th, 2022
1,230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 6.88 KB | None | 0 0
  1. use std::collections::HashMap;
  2.  
  3. pub type Value = i32;
  4. pub type Result = std::result::Result<(), Error>;
  5.  
  6. type Stackop = fn(&mut Forth);
  7.  
  8. pub struct Builtin {
  9.     stack_min: usize,
  10.     func: Stackop
  11. }
  12.  
  13. pub struct Forth {
  14.     v: Vec<Value>,
  15.     f: HashMap<String,usize>,
  16.     b: HashMap<String,Builtin>,
  17.     s: Vec<Vec<String>>,
  18.     func: Vec<String>,
  19. }
  20.  
  21. #[derive(Debug, PartialEq)]
  22. pub enum Error {
  23.     DivisionByZero,
  24.     StackUnderflow,
  25.     UnknownWord,
  26.     InvalidWord,
  27. }
  28.  
  29. impl Forth {
  30.     pub fn op_drop(&mut self) {
  31.         self.v.pop();
  32.     }
  33.    
  34.     pub fn op_dup(&mut self) {
  35.         let temp = self.v[self.v.len() - 1];
  36.         self.v.push(temp);
  37.     }
  38.    
  39.     pub fn op_over(&mut self) {
  40.         let temp = self.v[self.v.len() - 2];
  41.         self.v.push(temp);
  42.     }
  43.    
  44.     pub fn op_swap(&mut self) {
  45.         let size = self.v.len();
  46.         let temp = self.v[size - 2];
  47.         self.v[size - 2] = self.v[size - 1];
  48.         self.v[size - 1] = temp;
  49.     }
  50.    
  51.     pub fn new() -> Forth {
  52.         let mut temp: Vec<Vec<String>> = Vec::new();
  53.         temp.push(Vec::new());
  54.         let mut ftab: HashMap::<String,Builtin> = HashMap::new();
  55.         ftab.insert("drop".to_string(), Builtin{stack_min:1,func:Self::op_drop});
  56.         ftab.insert("dup" .to_string(), Builtin{stack_min:1,func:Self::op_dup});
  57.         ftab.insert("over".to_string(), Builtin{stack_min:2,func:Self::op_over});
  58.         ftab.insert("swap".to_string(), Builtin{stack_min:2,func:Self::op_swap});
  59.         Forth{v: Vec::<Value>::new(), f: HashMap::new(), b:ftab, s: temp, func: Vec::new()}
  60.     }
  61.  
  62.     pub fn stack(&self) -> &[Value] {
  63.         &self.v
  64.     }
  65.  
  66.     pub fn eval(&mut self, input: &str) -> Result {
  67.         self.v.clear();
  68.         self.s[0].clear();
  69.         println!("\neval({})", input);
  70.  
  71.         // Parse the input text and store it in a vector
  72.         {
  73.             let temp: Vec<&str> = input.split(' ').collect();
  74.             let n = temp.len() as i32;
  75.             for x in 0..n as usize {
  76.                 self.s[0].push(String::from(temp[x]));
  77.             }
  78.         }
  79.         Self::exec(self, 0)
  80.     }
  81.  
  82.     pub fn exec(&mut self, sx: usize) -> Result {
  83.    
  84.         let n: usize = self.s[sx].len();
  85.         let mut collecting = false;
  86.        
  87.         // User-defined functions store the function name at index 0,
  88.         // so start with 1 unless it's the primary input line (sx == 0)
  89.         let lo:usize = if sx == 0 {0} else {1};
  90.  
  91.         for x in lo..n as usize {
  92.            
  93.             let word = &self.s[sx][x];
  94.  
  95.             if word == ";" {
  96.                 if collecting {
  97.                     collecting = false;
  98.                     let index: usize = self.s.len(); // 1 for main + 1 for each function
  99.                     self.s.push(Vec::<String>::new()); // Create vec for new user-def function
  100.                     for item in self.func.iter() {
  101.                         if self.s[index].len() > 0 && self.appropriate(&item,index)
  102.                         {
  103.                             let sx = *self.f.get(item).unwrap();
  104.                             let n = self.s[sx].len();
  105.                             for x in 1..n as usize {
  106.                                 let symbol = self.s[sx][x].clone();
  107.                                 self.s[index].push(symbol);
  108.                             }
  109.                         }
  110.                         else {
  111.                             self.s[index].push(item.to_string());
  112.                         }
  113.                     }
  114.                     self.f.insert(self.s[index][0].clone().to_lowercase(), index);
  115.                     self.func.clear();
  116.                     continue;
  117.                 }
  118.                 continue;
  119.             }
  120.             if collecting {
  121.                 self.func.push(String::from(word));
  122.                 continue;
  123.             }
  124.  
  125.             if word == ":" {
  126.                 // There must be at least 3 more operands after a colon
  127.                 if self.s[sx].len() < x + 4 {return Err(Error::InvalidWord);}
  128.                
  129.                 // In this implementation, numbers are not allowed to be function
  130.                 // names.
  131.                 match self.s[sx][x+1].parse::<Value>() {
  132.                     Ok(_) => { return Err(Error::InvalidWord); },
  133.                     _ => ()
  134.                 }
  135.                
  136.                 // It's not a number, so we can proceed.
  137.                 collecting = true;
  138.                 self.func.clear();
  139.                 continue;
  140.             }
  141.  
  142.             // Integer values are just pushed onto the stack
  143.             match word.parse::<Value>() {
  144.                 Ok(value) => { self.v.push(value); continue; },
  145.                 _ => {}
  146.             }
  147.  
  148.             // User-defined functions
  149.             let lower = word.to_lowercase();
  150.             if self.f.contains_key(&lower) {
  151.                 let sx = *self.f.get(&lower).unwrap();
  152.                 match Self::exec(self, sx) {
  153.                     Ok(_) => continue,
  154.                     Err(e) => return Err(e)
  155.                 };
  156.             }
  157.  
  158.             // Binary arithmetic operators
  159.             if Self::is_op(word) {
  160.                 if self.v.len() < 2 {
  161.                     return Err(Error::StackUnderflow);
  162.                 }
  163.                 let b = self.v.pop().unwrap();
  164.                 let a = self.v.pop().unwrap();
  165.                 let c = match word.as_str() {
  166.                     "+" => a + b,
  167.                     "-" => a - b,
  168.                     "*" => a * b,
  169.                     "/" => {if b == 0 {return Err(Error::DivisionByZero);} a / b},
  170.                     _ => 0
  171.                 };
  172.                 self.v.push(c);
  173.                 continue;
  174.             }
  175.            
  176.             // Built-in functions
  177.             let p = self.b.get(&lower);
  178.             match p {
  179.                 Some(param) => {
  180.                     if self.v.len() < param.stack_min {
  181.                         return Err(Error::StackUnderflow);
  182.                     }
  183.                     (param.func)(self);
  184.                     continue;
  185.                 },
  186.                 _ => { return Err(Error::UnknownWord); }
  187.             }
  188.         } // end loop
  189.  
  190.         Ok(())
  191.     }
  192.  
  193.     fn is_op(input: &str) -> bool {
  194.         match input {"+"|"-"|"*"|"/" => true, _ => false}
  195.     }
  196.  
  197.     fn appropriate(&self, item:&str, index:usize) -> bool
  198.     {
  199.         // Is it appropriate to emit the previous definition of a user-defined function?
  200.         if self.s[index][0] == item {
  201.             true // Yes because we are redefining a previously defined function
  202.         }
  203.         else {
  204.             if index >= self.s.len() {
  205.                 false // Guard to be sure index is meaningful
  206.             }
  207.             else {
  208.                 if let Some(&sx) = self.f.get(item) {
  209.                     // Yes if the previous definition is a single term
  210.                     // and therefore will not increase storage requirements.
  211.                     // Length 2 means 1 for the function name and 1 for its definition.
  212.                     self.s[sx].len() == 2
  213.                 }
  214.                 else {
  215.                     false
  216.                 }
  217.             }
  218.         }
  219.     }
  220. }
  221.  
  222.  
  223. fn main() {
  224.     let cmd = [
  225.         ": f over over + ;",
  226.         "1 1 f f f f f f f f f f f"
  227.     ];
  228.     let mut f = Forth::new();
  229.     for line in cmd {
  230.         f.eval(line);
  231.         println!("stack = {:?}", f.stack());
  232.     }
  233. }
  234.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement