Forth

1. Readme

Forth

为 Forth 的一个非常简单的子集,实现一个执行程序.

Forth是一种基于栈的编程语言。为 Forth 的一小部分子集,实现一个非常基本的执行器。

您的执行器必须支持以下关键字:

  • +-*/(整数运算)
  • DUPDROPSWAPOVER(栈操作)

您的执行器还必须支持使用惯用语法,定义新单词:: word-name definition ;.

为简单起见,您需要支持的唯一数据类型是,至少 16 位大小的有符号整数。

您应该对语法使用以下规则:一个 number 是一个或多个(ASCII)数字的序列,单词是一个或多个字母,数字,符号或标点符号的序列,而不是数字。(Forth 可能使用稍微不同的规则,但这已足够接近。)

单词不区分大小写。

2. 开始你的表演

pub type Value = i32;
pub type ForthResult = Result<(), Error>;

pub struct Forth;

#[derive(Debug, PartialEq)]
pub enum Error {
   DivisionByZero,
   StackUnderflow,
   UnknownWord,
   InvalidWord,
}

impl Forth {
   pub fn new() -> Forth {
       unimplemented!()
   }

   pub fn stack(&self) -> Vec<Value> {
       unimplemented!()
   }

   pub fn eval(&mut self, input: &str) -> ForthResult {
       unimplemented!("result of evaluating '{}'", input)
   }
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
#[test]
fn no_input_no_stack() {
   assert_eq!(Vec::<Value>::new(), Forth::new().stack());
}

#[test]
//#[ignore]
fn numbers_just_get_pushed_onto_the_stack() {
   let mut f = Forth::new();
   assert!(f.eval("1 2 3 4 5 -1").is_ok());
   assert_eq!(vec![1, 2, 3, 4, 5, -1], f.stack());
}

#[test]
//#[ignore]
fn non_word_characters_are_separators() {
   let mut f = Forth::new();
   // Note the Ogham Space Mark ( ), this is a spacing character.
   assert!(f.eval("1\u{0000}2\u{0001}3\n4\r5 6\t7").is_ok());
   assert_eq!(vec![1, 2, 3, 4, 5, 6, 7], f.stack());
}

#[test]
//#[ignore]
fn basic_arithmetic_1() {
   let mut f = Forth::new();
   assert!(f.eval("1 2 + 4 -").is_ok());
   assert_eq!(vec![-1], f.stack());
}

#[test]
//#[ignore]
fn basic_arithmetic_2() {
   let mut f = Forth::new();
   assert!(f.eval("2 4 * 3 /").is_ok());
   assert_eq!(vec![2], f.stack());
}

#[test]
//#[ignore]
fn addition_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("+"));
}

#[test]
//#[ignore]
fn subtraction_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("-"));
}

#[test]
//#[ignore]
fn multiplication_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("*"));
}

#[test]
//#[ignore]
fn division_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("/"));
}

#[test]
//#[ignore]
fn division_by_zero() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::DivisionByZero), f.eval("4 2 2 - /"));
}

#[test]
//#[ignore]
fn dup() {
   let mut f = Forth::new();
   assert!(f.eval("1 DUP").is_ok());
   assert_eq!(vec![1, 1], f.stack());
}

#[test]
//#[ignore]
fn dup_case_insensitive() {
   let mut f = Forth::new();
   assert!(f.eval("1 Dup").is_ok());
   assert_eq!(vec![1, 1], f.stack());
}

#[test]
//#[ignore]
fn dup_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("dup"));
}

#[test]
//#[ignore]
fn drop() {
   let mut f = Forth::new();
   assert!(f.eval("1 drop").is_ok());
   assert_eq!(Vec::<Value>::new(), f.stack());
}

#[test]
//#[ignore]
fn drop_with_two() {
   let mut f = Forth::new();
   assert!(f.eval("1 2 drop").is_ok());
   assert_eq!(vec![1], f.stack());
}

#[test]
//#[ignore]
fn drop_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("drop"));
}

#[test]
//#[ignore]
fn swap() {
   let mut f = Forth::new();
   assert!(f.eval("1 2 swap").is_ok());
   assert_eq!(vec![2, 1], f.stack());
}

#[test]
//#[ignore]
fn swap_with_three() {
   let mut f = Forth::new();
   assert!(f.eval("1 2 3 swap").is_ok());
   assert_eq!(vec![1, 3, 2], f.stack());
}

#[test]
//#[ignore]
fn swap_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("1 swap"));
   assert_eq!(Err(Error::StackUnderflow), f.eval("swap"));
}

#[test]
//#[ignore]
fn over() {
   let mut f = Forth::new();
   assert!(f.eval("1 2 over").is_ok());
   assert_eq!(vec![1, 2, 1], f.stack());
}

#[test]
//#[ignore]
fn over_with_three() {
   let mut f = Forth::new();
   assert!(f.eval("1 2 3 over").is_ok());
   assert_eq!(vec![1, 2, 3, 2], f.stack());
}

#[test]
//#[ignore]
fn over_error() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::StackUnderflow), f.eval("1 over"));
   assert_eq!(Err(Error::StackUnderflow), f.eval("over"));
}

#[test]
//#[ignore]
fn defining_a_new_word() {
   let mut f = Forth::new();
   assert!(f.eval(": CoUnT 1 2 3 ;").is_ok());
   assert!(f.eval("count COUNT").is_ok());
   assert_eq!(vec![1, 2, 3, 1, 2, 3], f.stack());
}

#[test]
//#[ignore]
fn redefining_an_existing_word() {
   let mut f = Forth::new();
   assert!(f.eval(": foo dup ;").is_ok());
   assert!(f.eval(": foo dup dup ;").is_ok());
   assert!(f.eval("1 foo").is_ok());
   assert_eq!(vec![1, 1, 1], f.stack());
}

#[test]
//#[ignore]
fn redefining_an_existing_built_in_word() {
   let mut f = Forth::new();
   assert!(f.eval(": swap dup ;").is_ok());
   assert!(f.eval("1 swap").is_ok());
   assert_eq!(vec![1, 1], f.stack());
}

#[test]
//#[ignore]
fn defining_words_with_odd_characters() {
   let mut f = Forth::new();
   assert!(f.eval(": € 220371 ; €").is_ok());
   assert_eq!(vec![220371], f.stack());
}

#[test]
//#[ignore]
fn defining_a_number() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::InvalidWord), f.eval(": 1 2 ;"));
}

#[test]
//#[ignore]
fn malformed_word_definition() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::InvalidWord), f.eval(":"));
   assert_eq!(Err(Error::InvalidWord), f.eval(": foo"));
   assert_eq!(Err(Error::InvalidWord), f.eval(": foo 1"));
}

#[test]
//#[ignore]
fn calling_non_existing_word() {
   let mut f = Forth::new();
   assert_eq!(Err(Error::UnknownWord), f.eval("1 foo"));
}

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
use std::collections::HashMap;
use std::collections::LinkedList;
use std::str::FromStr;

use Term::*;

pub type Value = i32;
pub type ForthResult = Result<(), Error>;
type StackResult<T> = Result<T, Error>;

type Stack = LinkedList<Value>;
type Code = LinkedList<Term>;
type Definitions = HashMap<String, Code>;

pub struct Forth {
   code: Code,
   defs: Definitions,
   stack: Stack,
}

#[derive(Debug, PartialEq)]
pub enum Error {
   DivisionByZero,
   StackUnderflow,
   UnknownWord,
   InvalidWord,
}

#[derive(Debug, Clone)]
enum Term {
   Number(Value),
   Word(String),
   StartDefinition,
   EndDefinition,
}

impl FromStr for Term {
   type Err = ();

   fn from_str(s: &str) -> Result<Term, ()> {
       match s {
           ":" => Ok(StartDefinition),
           ";" => Ok(EndDefinition),
           _ => Err(()),
       }.or_else(|_| Value::from_str(s).map(Number))
           .or_else(|_| Ok(Word(s.to_ascii_lowercase())))
   }
}

impl Forth {
   pub fn new() -> Forth {
       Forth {
           code: LinkedList::new(),
           defs: HashMap::new(),
           stack: LinkedList::new(),
       }
   }

   pub fn stack(&self) -> Vec<Value> {
       self.stack.iter().cloned().collect()
   }

   pub fn eval(&mut self, input: &str) -> ForthResult {
       let mut new_code = Forth::into_code(input);
       self.code.append(&mut new_code);
       self.run()
   }

   fn run(&mut self) -> ForthResult {
       while let Some(term) = self.code.pop_front() {
           try!(self.step_term(term))
       }

       Forth::ok()
   }

   fn step_term(&mut self, term: Term) -> ForthResult {
       match term {
           Number(value) => self.push(value),
           Word(word) => self.step_word(word),
           StartDefinition => self.store_definition(),
           EndDefinition => Err(Error::InvalidWord),
       }
   }

   fn step_word(&mut self, word: String) -> ForthResult {
       self.defs
           .get(&word)
           .ok_or(Error::UnknownWord)
           .map(Clone::clone)
           .map(|mut code| self.code.append(&mut code))
           .or_else(|_| self.step_built_in(&word))
   }

   fn step_built_in(&mut self, word: &String) -> ForthResult {
       match word.as_ref() {
           "+" => self.bin_op(|(a, b)| Ok(a + b)),
           "-" => self.bin_op(|(a, b)| Ok(a - b)),
           "*" => self.bin_op(|(a, b)| Ok(a * b)),
           "/" => self.bin_op(|(a, b)| a.checked_div(b).ok_or(Error::DivisionByZero)),
           "dup" => self.pop().and_then(|a| self.push(a).and(self.push(a))),
           "drop" => self.pop().and(Forth::ok()),
           "swap" => self.pop_two()
               .and_then(|(a, b)| self.push(b).and(self.push(a))),
           "over" => self.pop_two()
               .and_then(|(a, b)| self.push(a).and(self.push(b)).and(self.push(a))),
           _ => Err(Error::UnknownWord),
       }
   }

   fn store_definition(&mut self) -> ForthResult {
       let mut def = LinkedList::new();

       loop {
           match self.code.pop_front() {
               Some(EndDefinition) => break,
               Some(term) => def.push_back(term),
               None => return Err(Error::InvalidWord),
           }
       }

       if let Some(Word(name)) = def.pop_front() {
           self.store_word(name, def)
       } else {
           Err(Error::InvalidWord)
       }
   }

   fn push(&mut self, value: Value) -> ForthResult {
       self.stack.push_back(value);
       Forth::ok()
   }

   fn pop(&mut self) -> StackResult<Value> {
       self.stack.pop_back().ok_or(Error::StackUnderflow)
   }

   fn pop_two(&mut self) -> StackResult<(Value, Value)> {
       self.pop().and_then(|b| self.pop().and_then(|a| Ok((a, b))))
   }

   fn bin_op<F>(&mut self, op: F) -> ForthResult
   where
       F: FnOnce((Value, Value)) -> StackResult<Value>,
   {
       self.pop_two()
           .and_then(op)
           .and_then(|value| self.push(value))
   }

   fn store_word(&mut self, name: String, code: Code) -> ForthResult {
       self.defs.insert(name, code);
       Forth::ok()
   }

   fn into_code(input: &str) -> LinkedList<Term> {
       input
           .split(|c: char| c.is_whitespace() || c.is_control())
           .map(Term::from_str)
           .filter(Result::is_ok)
           .map(Result::unwrap)
           .collect()
   }

   fn ok() -> ForthResult {
       Ok(())
   }
}

#}



填充/相关