| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- use std::collections::HashMap;
- use fancy_regex::Regex;
- use std::fmt;
- use std::fs::File;
- use std::io;
- use std::io::{BufRead, BufReader};
- use std::num::ParseFloatError;
- use std::rc::Rc;
- /*
- Types
- */
- #[derive(Clone)]
- enum RispExp {
- Bool(bool),
- Symbol(String),
- Number(f64),
- List(Vec<RispExp>),
- Func(fn(&[RispExp]) -> Result<RispExp, RispErr>),
- Lambda(RispLambda),
- }
- #[derive(Clone)]
- struct RispLambda {
- params_exp: Rc<RispExp>,
- body_exp: Rc<RispExp>,
- }
- impl fmt::Display for RispExp {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let str = match self {
- RispExp::Bool(a) => a.to_string(),
- RispExp::Symbol(s) => s.clone(),
- RispExp::Number(n) => n.to_string(),
- RispExp::List(list) => {
- let xs: Vec<String> = list.iter().map(|x| x.to_string()).collect();
- format!("({})", xs.join(","))
- }
- RispExp::Func(_) => "Function {}".to_string(),
- RispExp::Lambda(_) => "Lambda {}".to_string(),
- };
- write!(f, "{}", str)
- }
- }
- #[derive(Debug)]
- enum RispErr {
- Reason(String),
- }
- #[derive(Clone)]
- struct RispEnv<'a> {
- data: HashMap<String, RispExp>,
- outer: Option<&'a RispEnv<'a>>,
- }
- /*
- InPort
- */
- // TODO change to symbol(eof)
- struct InPort {
- line: String,
- lines: Vec<String>,
- cur_line: usize
- }
- impl InPort {
- fn init(filename: String) -> InPort {
- let file = File::open(filename).unwrap();
- let reader = io::BufReader::new(file).lines().map(|s| s.ok().unwrap().to_string()).collect();
- InPort {
- line : String::new(),
- lines: reader,
- cur_line: 0
- }
- }
- pub fn next_token(&mut self) -> String {
- loop {
- if self.line.is_empty() {
- self.line = self.lines.get(self.cur_line).unwrap_or(&"#<eof-object>".to_string()).to_string();
- self.cur_line = self.cur_line + 1;
- }
- if self.line.is_empty() {
- return "#<eof-object>".to_string();
- }
- let (token, rest) = InPort::tokenize(self.line.clone());
- self.line = rest;
- if !token.is_empty() {
- return token;
- }
- }
- }
- fn tokenize(expr: String) -> (String, String) {
- let re =
- Regex::new(r#"\s*(,@|[('`,)]|"(?:[\\].|[^\\"])*"|;.*|[^\s('"`,;)]*)(.*)"#).unwrap();
- let result = re.captures(&expr);
- let captures = result
- .expect("Error running regex")
- .expect("No match found");
- // println!("{}", captures.get(0).unwrap().as_str().to_string());
- (
- captures.get(1).unwrap().as_str().to_string(),
- captures.get(2).unwrap().as_str().to_string(),
- )
- }
- }
- // TODO change return type to Symbol
- fn read(inport: InPort) -> String {
- fn read_ahead(token: String) {
- match token {
- "(" => {
- let L = Vec::new();
- loop {
- let token = inport.next_token();
- if token == ")" {
- return L;
- } else {
- L.append(read_ahead(token));
- }
- }
- },
- _ => { println!("{}", token); }
- }
- }
- let token1 = inport.next_token();
- if token1 == "#<eof-object>".to_string() {
- return "#<eof-object>".to_string();
- }
- }
- fn parse_atom(token: &str) -> RispExp {
- match token.as_ref() {
- "true" => RispExp::Bool(true),
- "false" => RispExp::Bool(false),
- _ => {
- let potential_float: Result<f64, ParseFloatError> = token.parse();
- match potential_float {
- Ok(v) => RispExp::Number(v),
- Err(_) => RispExp::Symbol(token.to_string().clone()),
- }
- }
- }
- }
- /*
- Env
- */
- macro_rules! ensure_tonicity {
- ($check_fn:expr) => {{
- |args: &[RispExp]| -> Result<RispExp, RispErr> {
- let floats = parse_list_of_floats(args)?;
- let first = floats
- .first()
- .ok_or(RispErr::Reason("expected at least one number".to_string()))?;
- let rest = &floats[1..];
- fn f(prev: &f64, xs: &[f64]) -> bool {
- match xs.first() {
- Some(x) => $check_fn(prev, x) && f(x, &xs[1..]),
- None => true,
- }
- };
- Ok(RispExp::Bool(f(first, rest)))
- }
- }};
- }
- fn default_env<'a>() -> RispEnv<'a> {
- let mut data: HashMap<String, RispExp> = HashMap::new();
- data.insert(
- "+".to_string(),
- RispExp::Func(|args: &[RispExp]| -> Result<RispExp, RispErr> {
- let sum = parse_list_of_floats(args)?
- .iter()
- .fold(0.0, |sum, a| sum + a);
- Ok(RispExp::Number(sum))
- }),
- );
- data.insert(
- "-".to_string(),
- RispExp::Func(|args: &[RispExp]| -> Result<RispExp, RispErr> {
- let floats = parse_list_of_floats(args)?;
- let first = *floats
- .first()
- .ok_or(RispErr::Reason("expected at least one number".to_string()))?;
- let sum_of_rest = floats[1..].iter().fold(0.0, |sum, a| sum + a);
- Ok(RispExp::Number(first - sum_of_rest))
- }),
- );
- data.insert(
- "=".to_string(),
- RispExp::Func(ensure_tonicity!(|a, b| a == b)),
- );
- data.insert(
- ">".to_string(),
- RispExp::Func(ensure_tonicity!(|a, b| a > b)),
- );
- data.insert(
- ">=".to_string(),
- RispExp::Func(ensure_tonicity!(|a, b| a >= b)),
- );
- data.insert(
- "<".to_string(),
- RispExp::Func(ensure_tonicity!(|a, b| a < b)),
- );
- data.insert(
- "<=".to_string(),
- RispExp::Func(ensure_tonicity!(|a, b| a <= b)),
- );
- RispEnv { data, outer: None }
- }
- fn parse_list_of_floats(args: &[RispExp]) -> Result<Vec<f64>, RispErr> {
- args.iter().map(|x| parse_single_float(x)).collect()
- }
- fn parse_single_float(exp: &RispExp) -> Result<f64, RispErr> {
- match exp {
- RispExp::Number(num) => Ok(*num),
- _ => Err(RispErr::Reason("expected a number".to_string())),
- }
- }
- /*
- Eval
- */
- fn eval_if_args(arg_forms: &[RispExp], env: &mut RispEnv) -> Result<RispExp, RispErr> {
- let test_form = arg_forms
- .first()
- .ok_or(RispErr::Reason("expected test form".to_string()))?;
- let test_eval = eval(test_form, env)?;
- match test_eval {
- RispExp::Bool(b) => {
- let form_idx = if b { 1 } else { 2 };
- let res_form = arg_forms
- .get(form_idx)
- .ok_or(RispErr::Reason(format!("expected form idx={}", form_idx)))?;
- let res_eval = eval(res_form, env);
- res_eval
- }
- _ => Err(RispErr::Reason(format!(
- "unexpected test form='{}'",
- test_form.to_string()
- ))),
- }
- }
- fn eval_def_args(arg_forms: &[RispExp], env: &mut RispEnv) -> Result<RispExp, RispErr> {
- let first_form = arg_forms
- .first()
- .ok_or(RispErr::Reason("expected first form".to_string()))?;
- let first_str = match first_form {
- RispExp::Symbol(s) => Ok(s.clone()),
- _ => Err(RispErr::Reason(
- "expected first form to be a symbol".to_string(),
- )),
- }?;
- let second_form = arg_forms
- .get(1)
- .ok_or(RispErr::Reason("expected second form".to_string()))?;
- if arg_forms.len() > 2 {
- return Err(RispErr::Reason("def can only have two forms ".to_string()));
- }
- let second_eval = eval(second_form, env)?;
- env.data.insert(first_str, second_eval);
- Ok(first_form.clone())
- }
- fn eval_lambda_args(arg_forms: &[RispExp]) -> Result<RispExp, RispErr> {
- let params_exp = arg_forms
- .first()
- .ok_or(RispErr::Reason("expected args form".to_string()))?;
- let body_exp = arg_forms
- .get(1)
- .ok_or(RispErr::Reason("expected second form".to_string()))?;
- if arg_forms.len() > 2 {
- return Err(RispErr::Reason(
- "fn definition can only have two forms ".to_string(),
- ));
- }
- Ok(RispExp::Lambda(RispLambda {
- body_exp: Rc::new(body_exp.clone()),
- params_exp: Rc::new(params_exp.clone()),
- }))
- }
- fn eval_built_in_form(
- exp: &RispExp,
- arg_forms: &[RispExp],
- env: &mut RispEnv,
- ) -> Option<Result<RispExp, RispErr>> {
- match exp {
- RispExp::Symbol(s) => match s.as_ref() {
- "if" => Some(eval_if_args(arg_forms, env)),
- "def" => Some(eval_def_args(arg_forms, env)),
- "fn" => Some(eval_lambda_args(arg_forms)),
- _ => None,
- },
- _ => None,
- }
- }
- fn env_get(k: &str, env: &RispEnv) -> Option<RispExp> {
- match env.data.get(k) {
- Some(exp) => Some(exp.clone()),
- None => match &env.outer {
- Some(outer_env) => env_get(k, &outer_env),
- None => None,
- },
- }
- }
- fn parse_list_of_symbol_strings(form: Rc<RispExp>) -> Result<Vec<String>, RispErr> {
- let list = match form.as_ref() {
- RispExp::List(s) => Ok(s.clone()),
- _ => Err(RispErr::Reason(
- "expected args form to be a list".to_string(),
- )),
- }?;
- list.iter()
- .map(|x| match x {
- RispExp::Symbol(s) => Ok(s.clone()),
- _ => Err(RispErr::Reason(
- "expected symbols in the argument list".to_string(),
- )),
- })
- .collect()
- }
- fn env_for_lambda<'a>(
- params: Rc<RispExp>,
- arg_forms: &[RispExp],
- outer_env: &'a mut RispEnv,
- ) -> Result<RispEnv<'a>, RispErr> {
- let ks = parse_list_of_symbol_strings(params)?;
- if ks.len() != arg_forms.len() {
- return Err(RispErr::Reason(format!(
- "expected {} arguments, got {}",
- ks.len(),
- arg_forms.len()
- )));
- }
- let vs = eval_forms(arg_forms, outer_env)?;
- let mut data: HashMap<String, RispExp> = HashMap::new();
- for (k, v) in ks.iter().zip(vs.iter()) {
- data.insert(k.clone(), v.clone());
- }
- Ok(RispEnv {
- data,
- outer: Some(outer_env),
- })
- }
- fn eval_forms(arg_forms: &[RispExp], env: &mut RispEnv) -> Result<Vec<RispExp>, RispErr> {
- arg_forms.iter().map(|x| eval(x, env)).collect()
- }
- fn eval(exp: &RispExp, env: &mut RispEnv) -> Result<RispExp, RispErr> {
- match exp {
- RispExp::Symbol(k) => {
- env_get(k, env).ok_or(RispErr::Reason(format!("unexpected symbol k='{}'", k)))
- }
- RispExp::Bool(_a) => Ok(exp.clone()),
- RispExp::Number(_a) => Ok(exp.clone()),
- RispExp::List(list) => {
- let first_form = list
- .first()
- .ok_or(RispErr::Reason("expected a non-empty list".to_string()))?;
- let arg_forms = &list[1..];
- match eval_built_in_form(first_form, arg_forms, env) {
- Some(res) => res,
- None => {
- let first_eval = eval(first_form, env)?;
- match first_eval {
- RispExp::Func(f) => f(&eval_forms(arg_forms, env)?),
- RispExp::Lambda(lambda) => {
- let new_env = &mut env_for_lambda(lambda.params_exp, arg_forms, env)?;
- eval(&lambda.body_exp, new_env)
- }
- _ => Err(RispErr::Reason("first form must be a function".to_string())),
- }
- }
- }
- }
- RispExp::Func(_) => Err(RispErr::Reason("unexpected form".to_string())),
- RispExp::Lambda(_) => Err(RispErr::Reason("unexpected form".to_string())),
- }
- }
- fn main() {
- let env = &mut default_env();
- let mut reader = InPort::init("new.lisp".to_string());
- let mut token = String::new();
- read(reader);
- // read from file
- // let file = File::open("new.lisp").unwrap();
- // let lines = io::BufReader::new(file).lines();
- // let mut cur_line = String::new();
- // let mut token = String::new();
- // for line in lines {
- // let (token, cur_line) = tokenize(line.ok().unwrap().as_str().to_string());
- // println!("token {:?}", token);
- // println!("line {:?}", cur_line);
- // }
- /*
- loop {
- println!("risp >");
- let expr = slurp_expr();
- match parse_eval(expr, env) {
- Ok(res) => println!("// 🔥 => {}", res),
- Err(e) => match e {
- RispErr::Reason(msg) => println!("// 🙀 => {}", msg),
- },
- }
- }
- */
- }
|