1use anyhow::Result;
2use std::io::{stdin, stdout, Cursor};
3
4use crate::{
5 expression::{Expr, ExprId},
6 io::{Input, Output},
7 parser::Parser,
8 printer::{CcPrinter, GenericPrinter},
9 runner::LazyKRunner,
10};
11
12pub enum Style {
13 CombCalculus,
14 Unlambda,
15 Jot,
16 Iota,
17}
18
19pub struct LazyKProgram {
20 runner: LazyKRunner,
21 root_id: ExprId,
22 output_limit: Option<usize>,
23}
24
25impl LazyKProgram {
27 pub fn compile(source: &str) -> Result<Self> {
36 let mut runner = LazyKRunner::new();
37 let root_id = Parser::parse(source, &mut runner)?;
38 Ok(Self {
39 runner,
40 root_id,
41 output_limit: None,
42 })
43 }
44
45 pub fn set_output_limit(&mut self, value: Option<usize>) {
48 self.output_limit = value;
49 }
50
51 pub fn run_vec(&mut self, input: Vec<u8>) -> Result<Vec<u8>> {
53 let input = Input::Reader(Box::new(Cursor::new(input)));
54 let mut output = Output::Buffer(Vec::new());
55 self.runner
56 .run(self.root_id, input, &mut output, self.output_limit)?;
57 match output {
58 Output::Buffer(result) => Ok(result),
59 _ => panic!("Unreachable code."),
60 }
61 }
62
63 pub fn run_string(&mut self, input: &str) -> Result<String> {
65 let result = self.run_vec(input.as_bytes().to_owned())?;
66 String::from_utf8(result).map_err(anyhow::Error::from)
67 }
68
69 pub fn run_console(&mut self) -> Result<()> {
71 let input = Input::Reader(Box::new(stdin().lock()));
72 let mut output = Output::Writer(Box::new(stdout().lock()));
73 self.runner
74 .run(self.root_id, input, &mut output, self.output_limit)?;
75 Ok(())
76 }
77
78 pub fn to_source(&self, style: Style) -> String {
92 match style {
93 Style::CombCalculus => CcPrinter::new(&self.runner).print(self.root_id),
94 _ => GenericPrinter::new(&self.runner, style).print(self.root_id),
95 }
96 }
97
98 pub fn make_printer(bytes: &[u8]) -> LazyKProgram {
106 let mut runner = LazyKRunner::new();
107 let eof = runner.church_char(256);
108 let mut list = runner.pair(eof, runner.k);
109 for i in (0..bytes.len()).rev() {
110 list = runner.pair(runner.church_char(bytes[i] as u16), list);
111 }
112 let root_id = runner.new_expr(Expr::K1(list));
113 Self {
114 runner,
115 root_id,
116 output_limit: None,
117 }
118 }
119}