aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-10 00:04:33 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-10 00:04:33 +0300
commit23c0ebf75d244b21b0f5ae9e21ada64a67444fd0 (patch)
tree7fbdfefdf5583a703ad2b2b7ee9f6d8e44aa4750 /src/main.rs
parenta2ca4c08dcbb5c08e210bc741141290a136a8de4 (diff)
downloadmyslip-23c0ebf75d244b21b0f5ae9e21ada64a67444fd0.tar.gz
myslip-23c0ebf75d244b21b0f5ae9e21ada64a67444fd0.zip
Added let bind history to REPL + other minor refactors in REPL
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs100
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(())
+
}