rearchitecturing

This commit is contained in:
Able 2024-11-15 05:15:44 -06:00
parent e8a086297c
commit 122fde0c40
6 changed files with 136 additions and 88 deletions

View file

@ -0,0 +1 @@
(def start (fn () (+ 1 1)))

View file

@ -1,7 +1,7 @@
use crate::parse_list_of_floats; use crate::lib::parse_list_of_floats;
use crate::Expr; use crate::lib::Expr;
use crate::HashMap; use crate::lib::HashMap;
use crate::RispError; use crate::lib::RispError;
macro_rules! ensure_tonicity { macro_rules! ensure_tonicity {
($check_fn:expr) => {{ ($check_fn:expr) => {{
@ -49,6 +49,7 @@ pub fn default_env<'a>() -> Environ<'a> {
Ok(Expr::Number(sum)) Ok(Expr::Number(sum))
}), }),
); );
data.insert( data.insert(
"-".to_string(), "-".to_string(),
Expr::Func(|args: &[Expr]| -> Result<Expr, RispError> { Expr::Func(|args: &[Expr]| -> Result<Expr, RispError> {

View file

@ -1,10 +1,10 @@
use crate::environ::env_get; use crate::lib::environ::env_get;
use crate::Environ; use crate::lib::Environ;
use crate::Expr; use crate::lib::Expr;
use crate::HashMap; use crate::lib::HashMap;
use crate::RLambda; use crate::lib::RLambda;
use crate::Rc; use crate::lib::Rc;
use crate::RispError; use crate::lib::RispError;
pub fn eval(exp: &Expr, env: &mut Environ) -> Result<Expr, RispError> { pub fn eval(exp: &Expr, env: &mut Environ) -> Result<Expr, RispError> {
match exp { match exp {
@ -14,6 +14,8 @@ pub fn eval(exp: &Expr, env: &mut Environ) -> Result<Expr, RispError> {
Expr::Bool(_a) => Ok(exp.clone()), Expr::Bool(_a) => Ok(exp.clone()),
Expr::Number(_a) => Ok(exp.clone()), Expr::Number(_a) => Ok(exp.clone()),
Expr::Str(_a)=>{ Ok(exp.clone())}
Expr::List(list) => { Expr::List(list) => {
let first_form = list let first_form = list
.first() .first()

74
src/lib/mod.rs Normal file
View file

@ -0,0 +1,74 @@
use core::fmt;
use core::num::ParseFloatError;
pub use std::collections::HashMap;
pub use std::io::Write;
pub use std::rc::Rc;
mod environ;
pub use environ::default_env;
pub use environ::Environ;
pub use environ::env_get;
mod parser;
pub use parser::parse;
pub use parser::parse_eval;
pub use parser::parse_list_of_floats;
mod evaluate;
#[derive(Debug)]
pub enum RispError {
Reason(String),
}
#[derive(Clone)]
pub enum Expr {
Bool(bool),
Symbol(String),
Number(f64),
Str(String),
List(Vec<Expr>),
Func(fn(&[Expr]) -> Result<Expr, RispError>),
Lambda(RLambda),
}
#[derive(Clone)]
pub struct RLambda {
params_exp: Rc<Expr>,
body_exp: Rc<Expr>,
}
impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Expr::*;
let str = match self {
Bool(a) => a.to_string(),
Symbol(s) => s.clone(),
Number(n) => n.to_string(),
Str(s) => format!("\"{}\"", s),
List(list) => {
let xs: Vec<String> = list.iter().map(|x| x.to_string()).collect();
format!("({})", xs.join(","))
}
Func(_) => "Function {}".to_string(),
Lambda(_) => "Lambda {}".to_string(),
};
write!(f, "{}", str)
}
}
fn read_seq<'a>(tokens: &'a [String]) -> Result<(Expr, &'a [String]), RispError> {
let mut res: Vec<Expr> = vec![];
let mut xs = tokens;
loop {
let (next_token, rest) = xs
.split_first()
.ok_or(RispError::Reason("could not find closing `)`".to_string()))?;
if next_token == ")" {
return Ok((Expr::List(res), rest)); // skip `)`, head to the token after
}
let (exp, new_xs) = parse(&xs)?;
res.push(exp);
xs = new_xs;
}
}

View file

@ -1,9 +1,9 @@
use crate::evaluate::eval; use crate::lib::evaluate::eval;
use crate::read_seq; use crate::lib::read_seq;
use crate::Environ; use crate::lib::Environ;
use crate::Expr; use crate::lib::Expr;
use crate::ParseFloatError; use crate::lib::ParseFloatError;
use crate::RispError; use crate::lib::RispError;
pub fn tokenize(expr: String) -> Vec<String> { pub fn tokenize(expr: String) -> Vec<String> {
expr.replace("(", " ( ") expr.replace("(", " ( ")
@ -44,7 +44,19 @@ fn parse_atom(token: &str) -> Expr {
let potential_float: Result<f64, ParseFloatError> = token.parse(); let potential_float: Result<f64, ParseFloatError> = token.parse();
match potential_float { match potential_float {
Ok(v) => Number(v), Ok(v) => Number(v),
Err(_) => Symbol(token.to_string().clone()), Err(er) => {
if token.to_string().starts_with("\"") && token.to_string().ends_with("\""){
let mut stri = token.to_string().clone();
stri.remove(0);
stri.pop();
Str(stri)
}else{
Symbol(token.to_string().clone())
}
}
} }
} }
} }

View file

@ -2,75 +2,9 @@ use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::io; use std::io;
use std::io::Write; use std::io::Write;
use std::num::ParseFloatError;
use std::rc::Rc;
mod environ; mod lib;
use environ::default_env; use lib::*;
use environ::Environ;
mod parser;
use parser::parse;
use parser::parse_eval;
use parser::parse_list_of_floats;
mod evaluate;
#[derive(Debug)]
enum RispError {
Reason(String),
}
#[derive(Clone)]
enum Expr {
Bool(bool),
Symbol(String),
Number(f64),
List(Vec<Expr>),
Func(fn(&[Expr]) -> Result<Expr, RispError>),
Lambda(RLambda),
}
#[derive(Clone)]
struct RLambda {
params_exp: Rc<Expr>,
body_exp: Rc<Expr>,
}
impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Expr::*;
let str = match self {
Bool(a) => a.to_string(),
Symbol(s) => s.clone(),
Number(n) => n.to_string(),
List(list) => {
let xs: Vec<String> = list.iter().map(|x| x.to_string()).collect();
format!("({})", xs.join(","))
}
Func(_) => "Function {}".to_string(),
Lambda(_) => "Lambda {}".to_string(),
};
write!(f, "{}", str)
}
}
fn read_seq<'a>(tokens: &'a [String]) -> Result<(Expr, &'a [String]), RispError> {
let mut res: Vec<Expr> = vec![];
let mut xs = tokens;
loop {
let (next_token, rest) = xs
.split_first()
.ok_or(RispError::Reason("could not find closing `)`".to_string()))?;
if next_token == ")" {
return Ok((Expr::List(res), rest)); // skip `)`, head to the token after
}
let (exp, new_xs) = parse(&xs)?;
res.push(exp);
xs = new_xs;
}
}
fn slurp_expr() -> String { fn slurp_expr() -> String {
let mut expr = String::new(); let mut expr = String::new();
@ -82,10 +16,34 @@ fn slurp_expr() -> String {
expr expr
} }
fn extend_environ<'a>(mut env: Environ<'a>) -> Environ<'a> {
env.data.insert(
"quit".to_string(),
Expr::Func(|args: &[Expr]| -> Result<Expr, RispError> {
// TODO: let this function take in arguments
println!("Exiting.");
std::process::exit(0);
Err(RispError::Reason("Cannot exit process".to_string()))
}),
);
env.data.insert(
"prompt".to_string(),
Expr::Symbol("risp => ".to_string()),
);
env
}
fn main() { fn main() {
let env = &mut default_env(); let mut env = &mut default_env();
let mut env = &mut extend_environ(env.clone());
loop { loop {
print!("risp > "); let prompt = env_get("prompt", env).unwrap_or(lib::Expr::Symbol("risp => ".to_string()));
print!("{}", prompt);
let _ = std::io::stdout().flush(); let _ = std::io::stdout().flush();
let expr = slurp_expr(); let expr = slurp_expr();
match parse_eval(expr, env) { match parse_eval(expr, env) {