1use crate::{ansi, ctx};
2use cl_ast::Stmt;
3use cl_interpret::convalue::ConValue;
4use cl_lexer::Lexer;
5use cl_parser::Parser;
6use repline::{error::ReplResult, prebaked::*};
7
8pub fn clear() {
9 print!("{}", ansi::CLEAR_ALL);
10 banner()
11}
12
13pub fn banner() {
14 println!("--- conlang v{} 💪🦈 ---", env!("CARGO_PKG_VERSION"))
15}
16
17pub fn main_menu(ctx: &mut ctx::Context) -> ReplResult<()> {
19 banner();
20 run(ctx)?;
21 read_and(ansi::GREEN, "mu>", " ?>", |line| {
22 match line.trim() {
23 "clear" => clear(),
24 "l" | "lex" => lex(ctx)?,
25 "f" | "fmt" => fmt(ctx)?,
26 "r" | "run" => run(ctx)?,
27 "q" | "quit" => return Ok(Response::Break),
28 "h" | "help" => println!(
29 "Valid commands
30 lex (l): Spin up a lexer, and lex some lines
31 fmt (f): Format the input
32 run (r): Enter the REPL, and evaluate some statements
33 help (h): Print this list
34 quit (q): Exit the program"
35 ),
36 _ => Err("Unknown command. Type \"help\" for help")?,
37 }
38 Ok(Response::Accept)
39 })
40}
41
42pub fn run(ctx: &mut ctx::Context) -> ReplResult<()> {
43 use cl_ast::ast_visitor::Fold;
44 use cl_parser::inliner::ModuleInliner;
45
46 read_and(ansi::CYAN, "cl>", " ?>", |line| {
47 if line.trim().is_empty() {
48 return Ok(Response::Deny);
49 }
50 let code = Parser::new("", Lexer::new(line)).parse::<Stmt>()?;
51 let code = ModuleInliner::new(".").fold_stmt(code);
52
53 print!("{}", ansi::OUTPUT);
54 match ctx.run(&code) {
55 Ok(ConValue::Empty) => print!("{}", ansi::RESET),
56 Ok(v) => println!("{}{v}", ansi::RESET),
57 Err(e) => println!("{}! > {e}{}", ansi::RED, ansi::RESET),
58 }
59 Ok(Response::Accept)
60 })
61}
62
63pub fn lex(_ctx: &mut ctx::Context) -> ReplResult<()> {
64 read_and(ansi::BRIGHT_BLUE, "lx>", " ?>", |line| {
65 for token in Lexer::new(line) {
66 match token {
67 Ok(token) => crate::tools::print_token(&token),
68 Err(e) => eprintln!("! > {}{e}{}", ansi::RED, ansi::RESET),
69 }
70 }
71
72 Ok(Response::Accept)
73 })
74}
75
76pub fn fmt(_ctx: &mut ctx::Context) -> ReplResult<()> {
77 read_and(ansi::BRIGHT_MAGENTA, "cl>", " ?>", |line| {
78 let mut p = Parser::new("", Lexer::new(line));
79
80 match p.parse::<Stmt>() {
81 Ok(code) => println!("{}{code}{}", ansi::OUTPUT, ansi::RESET),
82 Err(e) => Err(e)?,
83 }
84
85 Ok(Response::Accept)
86 })
87}