Теперь, когда у нас есть синтаксический анализатор и вычислитель, мы можем объединить их, чтобы создать цикл чтения-оценки-печати. Основная идея REPL состоит в том, чтобы прочитать строку из ввода, проанализировать ее, оценить и распечатать результат. Без какой-либо причудливой логики мы можем просто использовать то, что мы уже построили, чтобы создать что-то вроде этого:
pub fn repl(context: &mut Context) {
loop {
print!("> ");
let _ = io::stdout().flush();
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Error reading from stdin");
if input.contains(":=") {
match parse_binding(input) { Result::Err(e) => {
println!("{}", e);
}, Result::Ok((k,v)) => {
context.bind_global(&k,v);
}}
} else {
match parse_rhs(input) { Result::Err(e) => {
println!("{}", e);
}, Result::Ok(program) => {
match eval_rhs(context.clone(), &program) { Result::Err(e) => {
println!("{}", e);
}, Result::Ok(r) => {
println!("{}", r.to_string());
}}
}}
}
}
}
Затем, предоставляя эту функцию CLI, мы получаем работающий цикл чтения-оценки-печати.
lambda_calculus repl > f := λx. x x > f := λx x. x > f a (a a) > f a a a >
Полный пример рабочего кода доступен на GitHub. Далее мы реализуем простую систему типов и вывод типов.
Если вам нравится эта серия, рассмотрите возможность подписаться на Medium, это очень помогает поддерживать больше подобных работ.
Предыдущие статьи
Создание компилятора для современного функционального языка с нуля на Rust (Часть 1: Парсинг)
Создание компилятора для современного функционального языка с нуля в Rust (Часть 2: Оценка)
