starting to add an env so symbols can be found and functions run
This commit is contained in:
parent
f7f90cd78f
commit
9b252d9a6a
3 changed files with 69 additions and 35 deletions
80
src/main.rs
80
src/main.rs
|
@ -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()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
src/types.rs
22
src/types.rs
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue