Теперь, когда у нас есть синтаксический анализатор и вычислитель, мы можем объединить их, чтобы создать цикл чтения-оценки-печати. Основная идея 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: Оценка)