From 0fed41e6afbf32d274660cc3ec435686901d12c4 Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Wed, 25 Sep 2024 14:37:06 +0200 Subject: Introduce basic REPL --- rust/src/lambda.rs | 33 ++++++++++++++++++++++++++++++++- rust/src/main.rs | 9 +++++++-- rust/src/parser.rs | 1 - rust/tests/interpret_test.rs | 8 ++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) (limited to 'rust') diff --git a/rust/src/lambda.rs b/rust/src/lambda.rs index 97b6f08..416c31e 100644 --- a/rust/src/lambda.rs +++ b/rust/src/lambda.rs @@ -1,5 +1,9 @@ use rand::Rng; -use std::{collections::HashMap, fs::read_to_string}; +use std::{ + collections::HashMap, + fs::read_to_string, + io::{BufRead, BufReader, Read, Write}, +}; mod ast; use ast::*; @@ -58,6 +62,33 @@ pub fn eval_file(file_name: &str) -> String { .join(" ") } +pub fn repl(inp: &mut I, outp: &mut O) { + let mut env = Environment::new(); + let mut reader = BufReader::new(inp); + loop { + let mut input = String::new(); + write!(outp, "> ").unwrap(); + outp.flush().unwrap(); + match reader.read_line(&mut input) { + Ok(0) => break, + Ok(_) => (), + Err(e) => { + writeln!(outp, "{}", e).unwrap(); + break; + } + } + let values = parse(&input); + let results = values + .iter() + .map(|v| eval(v, &mut env)) + .collect::>(); + for result in results { + writeln!(outp, "{}", result).unwrap(); + outp.flush().unwrap(); + } + } +} + fn eval_all(values: &[Value]) -> Vec { let mut env = Environment::new(); values.iter().map(|v| eval(v, &mut env)).collect() diff --git a/rust/src/main.rs b/rust/src/main.rs index ffd92f2..136e868 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,11 +1,16 @@ -use std::env::args; +use std::{ + env::args, + io::{stdin, stdout}, +}; -use lambda::eval_file; +use lambda::{eval_file, repl}; fn main() { if args().count() > 1 { for file in args().skip(1) { println!("{}", eval_file(&file)); } + } else { + repl(&mut stdin(), &mut stdout()); } } diff --git a/rust/src/parser.rs b/rust/src/parser.rs index b065ec3..23a512b 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -76,7 +76,6 @@ fn parse_definition(parser: &mut Parser) -> Result { parser.backtrack(); e.to_string() })?; - println!("parser {:?}", parser); let var = parse_variable(parser)?; let body = parse_expression(parser)?; parser.expect(Token::RParen)?; diff --git a/rust/tests/interpret_test.rs b/rust/tests/interpret_test.rs index 61b0712..40c3ee5 100644 --- a/rust/tests/interpret_test.rs +++ b/rust/tests/interpret_test.rs @@ -7,3 +7,11 @@ fn interpreter_can_read_and_interpret_file() { assert_eq!("1", eval_file("sample/test_normal.txt")); assert_eq!("13", eval_file("sample/test_let.txt")); } + +#[test] +fn repl_can_read_and_interpret_input() { + let input = "(def id (lam x x))\n(id 12)"; + let mut output = Vec::new(); + lambda::repl(&mut input.as_bytes(), &mut output); + assert_eq!("> true\n> 12\n> ", String::from_utf8(output).unwrap()); +} -- cgit v1.2.3