Skip to content

Commit 0b4ea00

Browse files
authored
feat: add repl (#2)
Signed-off-by: Sn0rt <[email protected]>
1 parent 2031a4d commit 0b4ea00

File tree

8 files changed

+764
-26
lines changed

8 files changed

+764
-26
lines changed

Cargo.lock

Lines changed: 556 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
uuid = { version = "1.3", features = ["v4"] }
8+
rustyline = "8.0"
9+
log = "0.4"
10+
env_logger = "0.9"
11+
colored = "2.0"

README.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@
22

33
This project implements a Lambda Calculus interpreter in Rust. It supports various operations and Church encodings for numbers and boolean values.
44

5+
## REPL (Read-Eval-Print Loop)
6+
7+
This project includes a REPL for interactive use of the Lambda Calculus interpreter. To start the REPL, run the project's main executable.
8+
9+
### REPL Commands
10+
11+
The REPL supports the following commands:
12+
13+
- `:help` or `:?` - Show the help message
14+
- `:exit` - Exit the REPL
15+
- `:clear` - Clear the screen
16+
- `:last` - Show the last result
17+
- `:log <level>` - Set the log level (error, warn, info, debug, trace)
18+
19+
To evaluate a Lambda Calculus expression, simply type it into the REPL and press Enter.
20+
21+
### REPL Example
22+
23+
[![asciicast](https://asciinema.org/a/Vak2OEvfS9cNdmgSxuEmXYmkg.svg)](https://asciinema.org/a/Vak2OEvfS9cNdmgSxuEmXYmkg)
24+
525
## Supported Instructions
626

727
The interpreter supports the following instructions and operations:
@@ -72,6 +92,3 @@ Here are some examples of how to use the interpreter:
7292
(Y (λf. λn. (ifthenelse (is_zero n) 1 (multiply n (f (pred n))))))
7393
```
7494

75-
## Running Tests
76-
77-
To run the tests and see examples of the interpreter in action, use the following command:

src/lambda_parse.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::rc::Rc;
22
use std::iter::Peekable;
33
use std::vec::IntoIter;
44
use std::fmt;
5+
use log::debug;
56

67
// <expression> :== <abstraction> | <application> | <variable>
78
// <abstraction> :== λ <variable> . <expression>
@@ -123,6 +124,12 @@ pub struct ParseError {
123124
pub message: String,
124125
}
125126

127+
impl fmt::Display for ParseError {
128+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129+
write!(f, "{}", self.message)
130+
}
131+
}
132+
126133
pub fn parse_lambda(input: &str) -> Result<LambdaExpression, ParseError> {
127134
let mut tokens = tokenize(input);
128135
let result = parse_lambda_expression(&mut tokens);
@@ -192,7 +199,7 @@ fn parse_lambda_expression(tokens: &mut Peekable<IntoIter<String>>) -> Result<La
192199
argument: Rc::new(arg),
193200
};
194201
}
195-
println!("Updated expression: {:?}", expr);
202+
debug!("parse_expr: {:?}", expr);
196203
}
197204
Ok(expr)
198205
}

src/lambda_vm.rs

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::lambda_parse::{parse_lambda, LambdaExpression};
22
use std::rc::Rc;
33
use uuid::Uuid;
4+
use log::{debug, trace, info};
5+
use colored::*;
46

57
pub struct VM {
68
max_iterations: usize,
@@ -9,7 +11,7 @@ pub struct VM {
911
impl VM {
1012
pub fn new() -> Self {
1113
VM {
12-
max_iterations: 1000000, // 默认值
14+
max_iterations: 1000000, // default max iterations
1315
}
1416
}
1517

@@ -18,43 +20,56 @@ impl VM {
1820
}
1921

2022
pub fn eval(&self, expr: &LambdaExpression) -> Rc<LambdaExpression> {
21-
println!("Evaluating expression: {:?}", expr);
23+
debug!("{}", "Starting evaluation:".cyan().bold());
2224
let mut current = Rc::new(expr.clone());
23-
for _ in 0..self.max_iterations {
25+
for i in 0..self.max_iterations {
2426
let next = self.eval_recursive(&current, 0);
2527
if *next == *current {
28+
debug!("{}", "Evaluation complete:".green().bold());
29+
debug!(" {}", next.to_string().green());
2630
return next;
2731
}
2832
current = next;
33+
if i % 1000 == 0 {
34+
debug!("Iteration {}: {}", i, current.to_string());
35+
}
2936
}
37+
debug!("{}", "Reached maximum iterations".yellow().bold());
3038
current
3139
}
3240

3341
fn eval_recursive(&self, expr: &LambdaExpression, depth: usize) -> Rc<LambdaExpression> {
34-
println!("Depth: {}, Evaluating: {:?}", depth, expr);
3542
if depth >= self.max_iterations {
36-
println!("Reached maximum depth of {}", self.max_iterations);
43+
debug!("{}", "Reached maximum depth".yellow().bold());
3744
return Rc::new(expr.clone());
3845
}
3946

4047
let result = match expr {
41-
LambdaExpression::Variable(_) => Rc::new(expr.clone()),
42-
LambdaExpression::Number(_) => Rc::new(expr.clone()),
43-
LambdaExpression::Boolean(_) => Rc::new(expr.clone()),
48+
LambdaExpression::Variable(_) => {
49+
debug!("{}Variable: {}", " ".repeat(depth), expr.to_string());
50+
Rc::new(expr.clone())
51+
}
52+
LambdaExpression::Number(_) => {
53+
debug!("{}Number: {}", " ".repeat(depth), expr.to_string());
54+
Rc::new(expr.clone())
55+
}
56+
LambdaExpression::Boolean(_) => {
57+
debug!("{}Boolean: {}", " ".repeat(depth), expr.to_string());
58+
Rc::new(expr.clone())
59+
}
4460
LambdaExpression::Abstraction { parameter, body } => {
45-
println!("Depth: {}, Evaluating abstraction body", depth);
61+
debug!("{}Abstraction: {}", " ".repeat(depth), expr.to_string());
4662
Rc::new(LambdaExpression::Abstraction {
4763
parameter: parameter.clone(),
4864
body: self.eval_recursive(body, depth + 1),
4965
})
5066
}
5167
LambdaExpression::Application { function, argument } => {
52-
println!("Depth: {}, Evaluating application", depth);
68+
debug!("{}Application: {}", " ".repeat(depth), expr.to_string());
5369
let eval_func = self.eval_recursive(function, depth + 1);
5470
let eval_arg = self.eval_recursive(argument, depth + 1);
5571
match &*eval_func {
5672
LambdaExpression::Abstraction { parameter, body } => {
57-
println!("Depth: {}, Applying function", depth);
5873
let substituted = self.substitute(body, parameter, &eval_arg);
5974
self.eval_recursive(&substituted, depth + 1)
6075
}
@@ -65,17 +80,17 @@ impl VM {
6580
}
6681
}
6782
LambdaExpression::IsZero(inner) => {
83+
debug!("{}IsZero: {}", " ".repeat(depth), expr.to_string());
6884
let eval_inner = self.eval_recursive(inner, depth + 1);
69-
println!("IsZero: evaluating {:?}", eval_inner);
7085
match &*eval_inner {
7186
LambdaExpression::Abstraction { parameter: f, body } => {
7287
match &**body {
7388
LambdaExpression::Abstraction { parameter: x, body: inner_body } => {
7489
if **inner_body == LambdaExpression::Variable(x.clone()) {
75-
println!("IsZero: it is zero");
90+
trace!("{}IsZero: it is zero", " ".repeat(depth));
7691
Rc::new(parse_lambda("λx. λy. x").unwrap()) // true
7792
} else {
78-
println!("IsZero: it is not zero");
93+
trace!("{}IsZero: it is not zero", " ".repeat(depth));
7994
Rc::new(parse_lambda("λx. λy. y").unwrap()) // false
8095
}
8196
},
@@ -87,18 +102,17 @@ impl VM {
87102
},
88103
LambdaExpression::IfThenElse(condition, then_expr, else_expr) => {
89104
let eval_condition = self.eval_recursive(condition, depth + 1);
90-
println!("Evaluated condition: {:?}", eval_condition);
91105
match eval_condition.to_church_bool() {
92106
Some(true) => {
93-
println!("Condition is true, evaluating then_expr");
107+
debug!("{}Condition is true, evaluating then_expr", " ".repeat(depth));
94108
self.eval_recursive(then_expr, depth + 1)
95109
},
96110
Some(false) => {
97-
println!("Condition is false, evaluating else_expr");
111+
debug!("{}Condition is false, evaluating else_expr", " ".repeat(depth));
98112
self.eval_recursive(else_expr, depth + 1)
99113
},
100114
None => {
101-
println!("Condition is not a Church boolean, returning unevaluated IfThenElse");
115+
debug!("{}Condition is not a Church boolean, returning unevaluated IfThenElse", " ".repeat(depth));
102116
Rc::new(LambdaExpression::IfThenElse(
103117
eval_condition.clone(),
104118
then_expr.clone(),
@@ -107,8 +121,8 @@ impl VM {
107121
},
108122
}
109123
},
110-
111124
LambdaExpression::Pred(inner) => {
125+
debug!("{}Pred: {}", " ".repeat(depth), expr.to_string());
112126
let eval_inner = self.eval_recursive(inner, depth + 1);
113127
match &*eval_inner {
114128
LambdaExpression::Abstraction { .. } => {
@@ -125,6 +139,7 @@ impl VM {
125139
}
126140
}
127141
LambdaExpression::Succ(inner) => {
142+
debug!("{}Succ: {}", " ".repeat(depth), expr.to_string());
128143
let eval_inner = self.eval_recursive(inner, depth + 1);
129144
match &*eval_inner {
130145
LambdaExpression::Abstraction { .. } => {
@@ -164,6 +179,7 @@ impl VM {
164179
}
165180
}
166181
LambdaExpression::And(left, right) => {
182+
debug!("{}And: {}", " ".repeat(depth), expr.to_string());
167183
let eval_left = self.eval_recursive(left, depth + 1);
168184
let eval_right = self.eval_recursive(right, depth + 1);
169185
let true_expr = parse_lambda("λx. λy. x").unwrap();
@@ -186,6 +202,7 @@ impl VM {
186202
}
187203
}
188204
LambdaExpression::Not(inner) => {
205+
debug!("{}Not: {}", " ".repeat(depth), expr.to_string());
189206
let eval_inner = self.eval_recursive(inner, depth + 1);
190207
let true_expr = parse_lambda("λx. λy. x").unwrap();
191208
let false_expr = parse_lambda("λx. λy. y").unwrap();
@@ -196,18 +213,21 @@ impl VM {
196213
}
197214
}
198215
LambdaExpression::Pair(first, second) => {
216+
debug!("{}Pair: {}", " ".repeat(depth), expr.to_string());
199217
let eval_first = self.eval_recursive(first, depth + 1);
200218
let eval_second = self.eval_recursive(second, depth + 1);
201219
Rc::new(LambdaExpression::Pair(eval_first, eval_second))
202220
}
203221
LambdaExpression::First(pair) => {
222+
debug!("{}First: {}", " ".repeat(depth), expr.to_string());
204223
let eval_pair = self.eval_recursive(pair, depth + 1);
205224
match &*eval_pair {
206225
LambdaExpression::Pair(first, _) => first.clone(),
207226
_ => Rc::new(LambdaExpression::First(eval_pair)),
208227
}
209228
}
210229
LambdaExpression::Second(pair) => {
230+
debug!("{}Second: {}", " ".repeat(depth), expr.to_string());
211231
let eval_pair = self.eval_recursive(pair, depth + 1);
212232
match &*eval_pair {
213233
LambdaExpression::Pair(_, second) => second.clone(),
@@ -216,11 +236,14 @@ impl VM {
216236
}
217237
// not allow Y combinator nested
218238
// TODO
219-
LambdaExpression::YCombinator(f) => self.eval_y_combinator(f, depth),
239+
LambdaExpression::YCombinator(f) => {
240+
debug!("{}YCombinator: {}", " ".repeat(depth), expr.to_string());
241+
self.eval_y_combinator(f, depth)
242+
}
220243

221244
// show error and not support yet
222245
_ => {
223-
println!("Error: unsupported expression {:?}", expr);
246+
debug!("{}Unsupported expression: {}", " ".repeat(depth), expr.to_string());
224247
Rc::new(expr.clone())
225248
}
226249
};
@@ -993,7 +1016,7 @@ mod tests {
9931016
argument: Rc::new(input),
9941017
};
9951018

996-
println!("Starting evaluation");
1019+
println!("Starting evaluation of {:?}", result);
9971020
let result = vm.eval(&result);
9981021
println!("Evaluation complete");
9991022
println!("Result: {:?}", result);

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
pub mod lambda_parse;
22
pub mod lambda_vm;
3+
pub mod repl;
34

45
pub use lambda_parse::LambdaExpression;
56
pub use lambda_vm::{VM, church_encode, church_decode};
7+
pub use repl::run_repl;

src/main.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use lambda_vm::run_repl;
2+
use log::LevelFilter;
3+
use env_logger::Env;
4+
5+
fn main() {
6+
env_logger::Builder::from_env(Env::default().default_filter_or("debug"))
7+
.filter_module("lambda_vm", LevelFilter::Debug)
8+
.filter_module("rustyline", LevelFilter::Warn) // 将 rustyline 的日志级别设置为 Warn
9+
.format_timestamp(None)
10+
.init();
11+
12+
run_repl();
13+
}

0 commit comments

Comments
 (0)