starting to add an env so symbols can be found and functions run

This commit is contained in:
Chris Cochrun 2024-11-06 10:45:33 -06:00
parent f7f90cd78f
commit 9b252d9a6a
3 changed files with 69 additions and 35 deletions

View file

@ -1,8 +1,13 @@
use color_eyre::Result; use std::collections::HashMap;
use color_eyre::{
eyre::{eyre, ContextCompat},
Result,
};
use printer::print; use printer::print;
use reader::read; use reader::read;
use regex::Regex; use regex::Regex;
use rustyline::{config::Configurer, error::ReadlineError}; use rustyline::{config::Configurer, error::ReadlineError, Editor};
pub mod printer; pub mod printer;
pub mod reader; pub mod reader;
@ -10,15 +15,32 @@ pub mod types;
use types::*; use types::*;
fn main() -> Result<()> { fn main() -> Result<()> {
let mut rl = rustyline::DefaultEditor::new()?; 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); rl.set_edit_mode(rustyline::EditMode::Vi);
let env = Environment::default(); let mut env = Environment::default();
env.symbols.insert(
Symbol::from("+"),
Value::func(|args| {
let total = args
.iter()
.map(|a| match a {
Value::Number(a) => Ok(*a),
_ => Err(eyre!("Should be a number")),
})
.sum();
total
}),
);
loop { loop {
let entry = rl.readline(">> "); let entry = rl.readline(">> ");
match entry { match entry {
Ok(line) => { Ok(line) => {
rl.add_history_entry(line.as_str())?; rl.add_history_entry(line.as_str())?;
eval(line.as_str(), env.clone())?; read_eval_print(line.as_str(), &env)?;
} }
Err(ReadlineError::Interrupted) => { Err(ReadlineError::Interrupted) => {
println!("CTRL-C"); println!("CTRL-C");
@ -39,32 +61,34 @@ fn main() -> Result<()> {
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct Environment { pub struct Environment {
symbols: Vec<Symbol>, symbols: HashMap<Symbol, Value>,
functions: Vec<String>, outer: Box<Environment>,
keywords: Vec<String>,
} }
fn read_eval_print(str: &str) -> Result<()> { fn read_eval_print(str: &str, env: &Environment) -> Result<()> {
// print(eval(read(str))); print(&eval(&read(str), env).unwrap());
Ok(()) Ok(())
} }
fn eval(expr: &str, env: Environment) -> Result<()> { fn eval(expr: &Value, env: &Environment) -> Result<Value> {
let ast = read(expr); match expr {
let expr = print(&ast); Value::Symbol(s) => {
// let regex = Regex::new(r"^\(([[:ascii:]] .*)\)$").unwrap(); if let Some(symbol) = env.symbols.get(&s) {
// let exp = regex.captures_iter(&expr.expr); Ok(symbol.clone())
// for expr in exp { } else {
// // let regex = Regex::new(r#"^(\w)$"#).unwrap(); Err(eyre!("No symbol here"))
// // let mut atom = regex.captures_iter(atom?.get(0).unwrap().as_str()); }
// // for atom in atom { }
// // } Value::List(list) => {
// for atom in expr.iter() { let mut args = vec![];
// if let Some(atom) = atom { let func = &list[0];
// println!("{:?}", atom); for value in 1..list.len() {
// }; if let Ok(return_value) = eval(&list[value], env) {
// } args.push(return_value)
// } }
println!("{}", expr); }
Ok(()) func.apply(args)
}
value => Ok(value.to_owned()),
}
} }

View file

@ -23,7 +23,6 @@ pub fn print(value: &Value) -> String {
} }
Value::Number(n) => n.to_string(), Value::Number(n) => n.to_string(),
Value::Nil => "nil".to_string(), Value::Nil => "nil".to_string(),
Value::Function => "fn".to_string(),
Value::True => "t".to_string(), Value::True => "t".to_string(),
Value::Symbol(s) => s.0.clone(), Value::Symbol(s) => s.0.clone(),
Value::Keyword(k) => { Value::Keyword(k) => {
@ -31,6 +30,7 @@ pub fn print(value: &Value) -> String {
string.insert_str(0, ":"); string.insert_str(0, ":");
string string
} }
_ => "fn".to_string(),
} }
} }

View file

@ -1,4 +1,5 @@
use std::num::ParseIntError; use color_eyre::{eyre::eyre, Result};
use std::{num::ParseIntError, rc::Rc};
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Expression { pub struct Expression {
@ -15,6 +16,8 @@ impl From<&str> for Expression {
} }
} }
pub type LispArgs = Vec<Value>;
#[derive(Default, Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] #[derive(Default, Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum Value { pub enum Value {
List(Vec<Value>), List(Vec<Value>),
@ -22,7 +25,7 @@ pub enum Value {
Number(i64), Number(i64),
#[default] #[default]
Nil, Nil,
Function, Function(fn(LispArgs) -> Result<Value>, Rc<Value>),
True, True,
Symbol(Symbol), Symbol(Symbol),
Keyword(Keyword), Keyword(Keyword),
@ -35,6 +38,17 @@ impl Value {
_ => Self::Nil, _ => Self::Nil,
} }
} }
pub fn func(f: fn(LispArgs) -> Result<Value>) -> Self {
Self::Function(f, Rc::new(Self::Nil))
}
pub fn apply(&self, args: LispArgs) -> Result<Value> {
match self {
Self::Function(f, _) => f(args),
_ => Err(eyre!("No function here, shouldn't call apply")),
}
}
} }
impl From<Vec<Value>> for Value { impl From<Vec<Value>> for Value {
@ -54,10 +68,6 @@ impl From<&str> for Value {
Value::True Value::True
} else if s.starts_with(r#"""#) { } else if s.starts_with(r#"""#) {
Value::String(s.replace('"', "")) Value::String(s.replace('"', ""))
} else if s == "fn".to_owned() {
Value::Function
} else if s == "defun".to_owned() {
Value::Function
} else if s == "nil".to_owned() { } else if s == "nil".to_owned() {
Value::Nil Value::Nil
} else { } else {