From af9c2939072eff9ed6597d56e8744bbf41183d38 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 6 Feb 2025 21:35:17 -0600 Subject: [PATCH] cl-interpret, cl-repl: Move IO builtins into the CLI, so get_line can use repline keybinds. --- compiler/cl-interpret/src/builtin.rs | 19 +++---------------- compiler/cl-interpret/src/env.rs | 17 +++++++++++------ compiler/cl-repl/src/cli.rs | 27 ++++++++++++++++++++++++++- compiler/cl-repl/src/ctx.rs | 4 +--- compiler/cl-repl/src/menu.rs | 2 +- 5 files changed, 42 insertions(+), 27 deletions(-) diff --git a/compiler/cl-interpret/src/builtin.rs b/compiler/cl-interpret/src/builtin.rs index e4ca79f..0e0d27c 100644 --- a/compiler/cl-interpret/src/builtin.rs +++ b/compiler/cl-interpret/src/builtin.rs @@ -14,11 +14,11 @@ use std::{ #[derive(Clone, Copy)] pub struct Builtin { /// An identifier to be used during registration - name: &'static str, + pub name: &'static str, /// The signature, displayed when the builtin is printed - desc: &'static str, + pub desc: &'static str, /// The function to be run when called - func: &'static dyn Fn(&mut Environment, &[ConValue]) -> IResult, + pub func: &'static dyn Fn(&mut Environment, &[ConValue]) -> IResult, } impl Builtin { @@ -173,23 +173,10 @@ pub const Builtins: &[Builtin] = &builtins![ }) } - /// Gets a line of input from stdin - fn get_line() { - let mut line = String::new(); - let _ = std::io::stdin().read_line(&mut line); - Ok(line) - } - /// Returns a shark fn shark() { Ok('\u{1f988}') } - - /// Clears the screen - fn clear() { - println!("\x1b[G"); - Ok(()) - } ]; pub const Math: &[Builtin] = &builtins![ diff --git a/compiler/cl-interpret/src/env.rs b/compiler/cl-interpret/src/env.rs index c6aa59a..123aba6 100644 --- a/compiler/cl-interpret/src/env.rs +++ b/compiler/cl-interpret/src/env.rs @@ -52,16 +52,14 @@ impl Display for Environment { impl Default for Environment { fn default() -> Self { Self { - builtin: to_hashmap2(Builtins.iter().chain(Math.iter())), + builtin: to_hashmap(Builtins.iter().chain(Math.iter())), global: vec![(HashMap::new(), "globals")], frames: vec![], } } } -// fn to_hashmap(from: &[&'static dyn BuiltIn]) -> HashMap> { -// from.iter().map(|&v| (v.name(), Some(v.into()))).collect() -// } -fn to_hashmap2(from: impl IntoIterator) -> HashMap> { + +fn to_hashmap(from: impl IntoIterator) -> HashMap> { from.into_iter() .map(|v| (v.name(), Some(v.into()))) .collect() @@ -84,8 +82,15 @@ impl Environment { &self.builtin } - pub fn add_builtin(&mut self, builtin: &'static Builtin) { + pub fn add_builtin(&mut self, builtin: &'static Builtin) -> &mut Self { self.builtin.insert(builtin.name(), Some(builtin.into())); + self + } + + pub fn add_builtins(&mut self, builtins: &'static [Builtin]) { + for builtin in builtins { + self.add_builtin(builtin); + } } pub fn push_frame(&mut self, name: &'static str, frame: StackFrame) { diff --git a/compiler/cl-repl/src/cli.rs b/compiler/cl-repl/src/cli.rs index 2abaa22..37c0323 100644 --- a/compiler/cl-repl/src/cli.rs +++ b/compiler/cl-repl/src/cli.rs @@ -6,7 +6,7 @@ use crate::{ tools::print_token, }; use cl_ast::File; -use cl_interpret::{convalue::ConValue, env::Environment, interpret::Interpret}; +use cl_interpret::{builtin::builtins, convalue::ConValue, env::Environment, interpret::Interpret}; use cl_lexer::Lexer; use cl_parser::Parser; use std::{error::Error, path::Path}; @@ -16,6 +16,31 @@ pub fn run(args: Args) -> Result<(), Box> { let Args { file, include, mode, repl } = args; let mut env = Environment::new(); + + env.add_builtins(&builtins! { + /// Clears the screen + fn clear() { + menu::clear(); + Ok(ConValue::Empty) + } + /// Evaluates a quoted expression + fn eval(ConValue::Quote(quote)) @env { + env.eval(quote.as_ref()) + } + /// Executes a file + fn import(ConValue::String(path)) @env { + load_file(env, &**path).or(Ok(ConValue::Empty)) + } + + /// Gets a line of input from stdin + fn get_line() { + match repline::Repline::new("", "", "").read() { + Ok(line) => Ok(ConValue::String(line.into())), + Err(e) => Ok(ConValue::String(e.to_string().into())), + } + } + }); + for path in include { load_file(&mut env, path)?; } diff --git a/compiler/cl-repl/src/ctx.rs b/compiler/cl-repl/src/ctx.rs index 613eb55..ddafb85 100644 --- a/compiler/cl-repl/src/ctx.rs +++ b/compiler/cl-repl/src/ctx.rs @@ -1,6 +1,4 @@ -use cl_interpret::{ - env::Environment, error::IResult, interpret::Interpret, convalue::ConValue, -}; +use cl_interpret::{convalue::ConValue, env::Environment, error::IResult, interpret::Interpret}; #[derive(Clone, Debug)] pub struct Context { diff --git a/compiler/cl-repl/src/menu.rs b/compiler/cl-repl/src/menu.rs index bce6372..ec8d975 100644 --- a/compiler/cl-repl/src/menu.rs +++ b/compiler/cl-repl/src/menu.rs @@ -5,7 +5,7 @@ use cl_lexer::Lexer; use cl_parser::Parser; use repline::{error::ReplResult, prebaked::*}; -fn clear() { +pub fn clear() { println!("{}", ansi::CLEAR_ALL); banner() }