13个不稳定版本 (3个重大变更)
使用旧Rust 2015
0.7.1 | 2016年5月25日 |
---|---|
0.6.0 | 2016年5月24日 |
0.1.5 | 2015年12月27日 |
0.1.4 | 2015年6月24日 |
0.0.2 | 2015年3月2日 |
#27 in #false
39 个月下载量
18KB
331 行
repl
泛型REPL特性
版本
lib.rs
:
R(读取), E(评估), P(打印), L(循环)
use repl::{Repl, ReplEnv};
use self::CmdType::*;
use self::Exp::*;
use self::ReplErr::{Read, Eval};
use std::default::Default;
use std::fmt;
pub struct MyRepl;
#[derive(Default)]
pub struct MyReplEnv {
prompt: String,
}
impl ReplEnv for MyReplEnv {
fn preamble(&self) -> bool {
false
}
fn colorize(&self) -> bool {
false
}
fn prompt(&self) -> &str {
&self.prompt
}
}
pub enum CmdType {
Open,
Close,
}
pub enum Exp {
Cmd(CmdType),
Strn(String),
Exit,
Nil,
}
pub enum ReplErr {
Read(&'static str),
Eval(&'static str), // Print(String),
}
impl fmt::Display for ReplErr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let x = match *self {
Read(ref x) => x,
Eval(ref x) => x,
// Print(ref x) => x,
};
write!(f, "{}", x)
}
}
pub type MyReplResult = Result<Exp, ReplErr>;
impl Repl<Exp, ReplErr, MyReplEnv> for MyRepl {
fn preamble(&self, _: &MyReplEnv) -> &MyRepl {
self
}
fn read(&self, input: String, _: &MyReplEnv) -> MyReplResult {
match &input[..] {
"open" | "close" | "exit" => Ok(Strn(input)),
_ => Err(Read("invalid input")),
}
}
fn eval(&self, cmd: Exp, _: &MyReplEnv) -> MyReplResult {
match cmd {
Strn(ref x) if *x == "open" => Ok(Cmd(Open)),
Strn(ref x) if *x == "close" => Ok(Cmd(Close)),
Strn(ref x) if *x == "exit" => Ok(Exit),
_ => Err(Eval("invalid ast")),
}
}
fn print(&self, cmd: Exp, _: &MyReplEnv) -> MyReplResult {
match cmd {
Cmd(Open) => {
println!("opening...");
Ok(Nil)
}
Cmd(Close) => {
println!("closing...");
Ok(Nil)
}
Exit => {
println!("exiting...");
Ok(Exit)
}
_ => Ok(Nil),
}
}
fn break_loop(&self, cmd: &Exp, _: &MyReplEnv) -> bool {
match *cmd {
Exit => true,
_ => false,
}
}
}
fn main() {
let repl = MyRepl;
let env: MyReplEnv = Default::default();
test_read(&repl, &env);
test_eval(&repl, &env);
test_print(&repl, &env);
test_read_eval_print(&repl, &env);
test_break_loop(&repl, &env);
}
fn test_read(repl: &MyRepl, env: &MyReplEnv) {
assert!(repl.read("open".to_owned(), env).is_ok());
assert!(repl.read("close".to_owned(), env).is_ok());
assert!(repl.read("exit".to_owned(), env).is_ok());
assert!(repl.read("blah".to_owned(), env).is_err());
}
fn test_eval(repl: &MyRepl, env: &MyReplEnv) {
assert!(repl.eval(Strn("open".to_owned()), &env).is_ok());
assert!(repl.eval(Strn("close".to_owned()), &env).is_ok());
assert!(repl.eval(Strn("exit".to_owned()), &env).is_ok());
assert!(repl.eval(Nil, &env).is_err());
}
fn test_print(repl: &MyRepl, env: &MyReplEnv) {
assert!(repl.print(Cmd(Open), &env).is_ok());
assert!(repl.print(Cmd(Close), &env).is_ok());
assert!(repl.print(Exit, &env).is_ok());
assert!(repl.print(Nil, &env).is_ok());
}
fn test_read_eval_print(repl: &MyRepl, env: &MyReplEnv) {
assert!(repl.read("open".to_owned(), &env)
.and_then(|r| repl.eval(r, &env))
.and_then(|r| repl.print(r, &env))
.is_ok());
assert!(repl.read("close".to_owned(), &env)
.and_then(|r| repl.eval(r, &env))
.and_then(|r| repl.print(r, &env))
.is_ok());
assert!(repl.read("blah".to_owned(), &env)
.and_then(|r| repl.eval(r, &env))
.and_then(|r| repl.print(r, &env))
.is_err());
}
fn test_break_loop(repl: &MyRepl, env: &MyReplEnv) {
assert!(repl.break_loop(&Exit, &env));
assert!(!repl.break_loop(&Cmd(Open), &env));
}
依赖
~3.5MB
~53K SLoC