making this work as a library

This commit is contained in:
Chris Cochrun 2024-11-19 06:17:07 -06:00
parent ba5b02074d
commit 37af7ff0ef
4 changed files with 160 additions and 1 deletions

View file

@ -3,6 +3,10 @@ name = "crisp"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[lib]
crate-type = ["staticlib"]
path = "src/lib.rs"
[dependencies] [dependencies]
color-eyre = "0.6.3" color-eyre = "0.6.3"
lazy_static = "1.5.0" lazy_static = "1.5.0"

View file

@ -24,7 +24,11 @@ impl Environment {
if let Some(value) = self.symbols.get(symbol) { if let Some(value) = self.symbols.get(symbol) {
value value
} else { } else {
&Value::Nil if let Some(env) = &*self.outer {
env.get_symbol(symbol)
} else {
&Value::Nil
}
} }
} }
} }

138
src/lib.rs Normal file
View file

@ -0,0 +1,138 @@
use std::collections::HashMap;
use color_eyre::{
eyre::{eyre, ContextCompat},
Result,
};
use env::Environment;
use printer::print;
use reader::read;
use regex::Regex;
use rustyline::{config::Configurer, error::ReadlineError, Editor};
pub mod env;
pub mod macros;
pub mod printer;
pub mod reader;
pub mod types;
use types::*;
pub fn main() -> Result<()> {
let mut rl = Editor::<(), rustyline::history::DefaultHistory>::new().unwrap();
if rl.load_history(".mal-history").is_err() {
eprintln!("No previous history.");
}
rl.set_edit_mode(rustyline::EditMode::Vi);
let mut env = Environment::new();
env.insert_symbol(
Symbol::from("+"),
Value::func(|args| {
let nums: Vec<i64> = args
.iter()
.map(|a| match a {
Value::Number(a) => Ok(*a),
_ => Err(eyre!("Should be a number")),
})
.flatten()
.collect();
let total = nums
.into_iter()
.reduce(|acc, e| acc + e)
.expect("shouldn't fail");
Ok(Value::from(total))
}),
);
env.insert_symbol(
Symbol::from("-"),
Value::func(|args| {
let nums: Vec<i64> = args
.iter()
.map(|a| match a {
Value::Number(a) => Ok(*a),
_ => Err(eyre!("Should be a number")),
})
.flatten()
.collect();
let total = nums
.into_iter()
.reduce(|acc, n| acc - n)
.expect("shouldn't fail");
Ok(Value::from(total))
}),
);
loop {
let entry = rl.readline(">> ");
match entry {
Ok(line) => {
rl.add_history_entry(line.as_str())?;
match read_eval_print(line.as_str(), &mut env) {
Ok(s) => println!("{s}"),
Err(e) => eprintln!("{e}"),
}
}
Err(ReadlineError::Interrupted) => {
println!("CTRL-C");
break;
}
Err(ReadlineError::Eof) => {
println!("CTRL-D");
break;
}
Err(err) => {
println!("Error: {:?}", err);
break;
}
}
}
Ok(())
}
pub fn read_eval_print(str: &str, env: &mut Environment) -> Result<String> {
Ok(print(&eval(&read(str), env)?))
}
pub fn eval(expr: &Value, env: &mut Environment) -> Result<Value> {
match expr {
Value::Symbol(s) => {
let symbol = env.get_symbol(s).to_owned();
Ok(symbol)
}
Value::List(list) => {
let mut args = vec![];
let first = &list[0];
if let Value::List(_) = first {
eval(first, env)
} else if let Value::Symbol(s) = first {
if s == &Symbol("defvar".to_string()) {
let second = &list[1];
if let Value::Symbol(s) = second {
Ok(Value::Symbol(s.clone()))
} else {
todo!()
}
} else if s == &Symbol("let*".to_string()) {
todo!()
} else {
let first = eval(first, env)?;
for value in list.iter().skip(1) {
if let Ok(return_value) = eval(value, env) {
args.push(return_value)
}
}
first.apply(args)
}
} else {
let first = eval(first, env)?;
for value in list.iter().skip(1) {
if let Ok(return_value) = eval(value, env) {
args.push(return_value)
}
}
first.apply(args)
}
}
value => Ok(value.to_owned()),
}
}

View file

@ -104,6 +104,19 @@ fn eval(expr: &Value, env: &Environment) -> Result<Value> {
let first = &list[0]; let first = &list[0];
if let Value::List(_) = first { if let Value::List(_) = first {
eval(first, env) eval(first, env)
} else if let Value::Symbol(s) = first {
if s == &Symbol("defvar".to_string()) {
let second = &list[1];
if let Value::Symbol(s) = second {
Ok(Value::Symbol(s.clone()))
} else {
todo!()
}
} else if s == &Symbol("let*".to_string()) {
todo!()
} else {
todo!()
}
} else { } else {
let first = eval(first, env)?; let first = eval(first, env)?;
for value in list.iter().skip(1) { for value in list.iter().skip(1) {