1use std::{io, ops};
2
3use kure2::lang::State;
4
5use crate::commands::Node;
6
7pub mod commands;
8pub mod repl_helper;
9
10const WELCOME_MESSAGE: &str = "Welcome to the kure2-rs REPL! Type '.help' for assistance.";
11
12pub struct Repl {
13 pub commands: Node,
14 pub state: State,
15}
16
17impl Repl {
18 pub fn new() -> Self {
19 Self {
20 commands: Node::root(),
21 state: State::new(),
22 }
23 }
24
25 pub fn welcome(&self, mut out: impl io::Write) -> io::Result<()> {
26 writeln!(out, "{WELCOME_MESSAGE}")?;
27 Ok(())
28 }
29
30 pub fn process_input(
31 &mut self,
32 line: &str,
33 mut out: impl io::Write,
34 ) -> io::Result<ops::ControlFlow<()>> {
35 let line = line.trim();
36 if line.is_empty() || line.starts_with('{') {
37 Ok(ops::ControlFlow::Continue(()))
38 } else if line.starts_with('.') {
39 self.process_command(line, &mut out)
40 } else if let Some((var, expr)) = line.split_once('=') {
41 let result = self.state.assign(var.trim(), expr.trim());
42 match result {
43 Ok(()) => {}
44 Err(e) => writeln!(out, "Error: {e}")?,
45 }
46
47 Ok(ops::ControlFlow::Continue(()))
48 } else {
49 let result = self.state.exec(line);
50 match result {
51 Ok(value) => {
52 write!(out, "{}", value.display("<expr>"))?;
54 }
55 Err(e) => writeln!(out, "Error: {e}")?,
56 }
57
58 Ok(ops::ControlFlow::Continue(()))
59 }
60 }
61
62 fn process_command(
63 &mut self,
64 command: &str,
65 mut out: impl io::Write,
66 ) -> io::Result<ops::ControlFlow<()>> {
67 let args = command.split_whitespace().collect::<Vec<_>>();
68
69 let Some(node) = self.commands.traverse(&args) else {
70 writeln!(out, "Unknown command or invalid syntax")?;
71 return Ok(ops::ControlFlow::Continue(()));
72 };
73 let Some(func) = &node.func else {
74 writeln!(out, "Incomplete command")?;
75 return Ok(ops::ControlFlow::Continue(()));
76 };
77
78 func(&mut self.state, &mut out, &args)
79 }
80}