fsm_input_driven/
fsm-input-driven.rs1use std::io::Write;
2
3use bicoro::*;
4mod turnstile;
5use turnstile::create;
6
7pub struct Input(String);
9
10pub enum Output {
12 StdOut(String),
13 StdErr(String),
14 Flush,
15}
16
17pub fn needs_input() -> Coroutine<'static, Input, Output, turnstile::Input> {
20 fn loop_(input: Input) -> Coroutine<'static, Input, Output, turnstile::Input> {
22 match input.0.trim() {
23 "push" => result(turnstile::Input::Push),
24 "coin" => result(turnstile::Input::Coin),
25 other => {
26 let error = format!("Turnstile: 'I don't understand {}' \r\n", other);
27 let prompt = "What do you try instead?".to_string();
28
29 send(Output::StdErr(error))
30 .and_then(|()| send(Output::StdOut(prompt)))
31 .and_then(|()| send(Output::Flush))
32 .and_then(|()| receive())
33 .and_then(loop_) }
35 }
36 }
37 let initial_prompt = format!("What do you do?: ");
39 send(Output::StdOut(initial_prompt))
40 .and_then(|()| send(Output::Flush))
41 .and_then(|()| receive())
42 .and_then(loop_)
43}
44
45pub fn on_output(o: turnstile::Output) -> Coroutine<'static, Input, Output, ()> {
47 send(Output::StdOut(format!(
48 "Turnstile responds with: '{}'\r\n",
49 o.to_string()
50 )))
51}
52
53pub fn main() {
54 let turnstile = create();
55
56 let mut composed = send(Output::StdOut(
59 "You are stopped by a turnstile!\r\n".to_string(),
60 ))
61 .and_then(|()| send(Output::Flush))
62 .and_then(|()| subroutine(needs_input, on_output, turnstile));
63
64 loop {
67 match run_step(composed) {
68 StepResult::Done(_) => unreachable!(), StepResult::Yield { output, next } => {
70 match output {
71 Output::StdOut(o) => print!("{}", o),
72 Output::StdErr(e) => print!("{}", e),
73 Output::Flush => std::io::stdout().flush().unwrap(),
74 }
75 composed = *next;
76 }
77 StepResult::Next(fun) => {
78 let mut buf = String::new();
80 std::io::stdin().read_line(&mut buf).unwrap();
81 let input = Input(buf);
82 composed = fun(input);
83 }
84 }
85 }
86}