rail_lang/v1/corelib/
display.rs

1use std::fmt::Display;
2use std::io::{self, Stdout, Write};
3
4use crate::v1::rail_machine::{RailDef, RailType, RailVal};
5
6pub fn builtins() -> Vec<RailDef<'static>> {
7    vec![
8        printer("p", "Consumes one value and prints it.", &|a| {
9            print_or_die(|out| out.write_fmt(format_args!("{}", a)))
10        }),
11        printer(
12            "pl",
13            "Consumes one value, prints it, and prints a newline.",
14            &|a| print_or_die(|out| out.write_fmt(format_args!("{}\n", a))),
15        ),
16        RailDef::contextless("nl", "Prints a newline.", &[], &[], || {
17            print_or_die(|out| out.write(b"\n"))
18        }),
19        RailDef::on_state_noerr(
20            "status",
21            "Prints the current status of the program.",
22            &[],
23            &[],
24            |state| {
25                print_or_die(|out| out.write_fmt(format_args!("{}\n", state.stack)));
26                state
27            },
28        ),
29        RailDef::contextless(
30            "clear",
31            "When invoked in a terminal context, clears the screen.",
32            &[],
33            &[],
34            || clearscreen::clear().expect("Unable to clear screen"),
35        ),
36    ]
37}
38
39fn printer<'a, P>(name: &str, description: &str, p: &'a P) -> RailDef<'a>
40where
41    P: Fn(&dyn Display) + 'a,
42{
43    RailDef::on_state_noerr(name, description, &[RailType::A], &[], move |quote| {
44        let (a, quote) = quote.pop();
45        match a {
46            RailVal::String(a) => p(&a),
47            _ => p(&a),
48        }
49        quote
50    })
51}
52
53fn print_or_die<P, T>(p: P)
54where
55    P: Fn(&mut Stdout) -> io::Result<T>,
56{
57    let res = p(&mut io::stdout());
58    if res.is_err() {
59        std::process::exit(1);
60    }
61}