diff options
-rw-r--r-- | src/main.rs | 100 |
1 files changed, 64 insertions, 36 deletions
diff --git a/src/main.rs b/src/main.rs index c518b82..0c71fbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,64 +1,92 @@ use myslip::parse::parsetree::parse_to_ast; -use myslip::sexp::{SExp::*, SLeaf::Nil}; +use myslip::sexp::{SExp::*, SLeaf::{Nil, Let}, util::scons}; use std::{io, io::Write}; fn main() { match repl() { Ok(()) => println!("bye :)"), - Err(e) => { - println!("Error: {}", e); - main(); - }, + Err(e) => println!("Error: {}", e), } } -fn repl() -> Result<(), String> { - - let stdin = io::stdin(); - - let mut input = String::new(); - - let mut stdout = io::stdout(); - +fn prompt_line(stdin: &io::Stdin, stdout: &mut io::Stdout) -> Result<(bool, String), io::Error> { + let mut line = String::new(); print!("> "); match stdout.flush() { Ok(_) => (), Err(_) => println!("Enter s-expression:"), }; - let mut success = stdin.read_line(&mut input); + let code = stdin.read_line(&mut line)?; + Ok((code == 0, line)) +} - while success.is_ok() && input != "exit\n" { - if let Ok(0) = success { - print!("\n"); - break; - } +fn repl() -> Result<(), io::Error> { - let expression = match parse_to_ast(&input) { - Ok(SCons(a, b)) if *b == Atom(Nil) => Ok(*a), - t => t - }?; + let stdin = io::stdin(); + let mut stdout = io::stdout(); - let ty = expression.type_check().map_err(|e| e.to_string())?; + let mut binds = vec![]; - let result = expression.multistep()?; + loop { - println!("{} : {}", result, ty); + let (eof, input) = prompt_line(&stdin, &mut stdout)?; - print!("> "); - match stdout.flush() { - Ok(_) => (), - Err(_) => println!("Enter s-expression:"), + if eof || input == "exit\n" { + break; + } + + let mut expression = match parse_to_ast(&input) { + Ok(SCons(a, b)) if *b == Atom(Nil) => *a, + Ok(t) => t, + Err(e) => { + println!("Syntax error: {}", e); + continue; + }, }; - input.clear(); - success = stdin.read_line(&mut input); - } + match &expression { + SCons(l, r) if **l == Atom(Let) => match scons(expression.clone(), Nil).type_check() { + Ok(_) => { + binds.push(expression); + println!("Bind saved"); + continue; + }, + Err(e) => { + println!("Type error: {e}"); + continue; + } + }, + _ => (), + } + + for i in 1..=binds.len() { + expression = scons(binds[binds.len() - i].clone(), expression); + } + + let ty = match expression + .type_check() + .map_err(|e| e.to_string()) { + Ok(t) => t, + Err(e) => { + println!("Type error: {}", e); + continue; + }, + }; + + let result = match expression.multistep() { + Ok(t) => t, + Err(e) => { + println!("Runtime error: {}", e); + continue; + }, + }; + + println!("{} : {}", result, ty); - match success { - Ok(_) => Ok(()), - Err(e) => Err(format!("read error: {e}")), } + Ok(()) + } |