rearchitecturing
This commit is contained in:
parent
e8a086297c
commit
122fde0c40
|
@ -0,0 +1 @@
|
||||||
|
(def start (fn () (+ 1 1)))
|
|
@ -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> {
|
|
@ -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
74
src/lib/mod.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
98
src/main.rs
98
src/main.rs
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue