use std::io::Write; use std::panic::{RefUnwindSafe, catch_unwind}; use std::sync::Arc; use std::sync::mpsc::Receiver; use delsh::{builtins, interpreter::Interpreter, interpreter::Value}; use happylock::ThreadKey; use uuid::Uuid; use crate::pipe::{Message, MessageField}; use crate::processes::send_message; macro_rules! add_builtins { ($interpreter: expr => $($name: ident)*) => { $(add_builtin!($interpreter, $name);)* }; } macro_rules! add_builtin { ($interpreter: expr, $name: ident) => { add_builtin!($interpreter, stringify!($name), $name); }; ($interpreter: expr, $name: expr, $builtin: ident) => { $interpreter.set_atom( $name.to_uppercase().into(), Arc::new(Value::RustFn(builtins::$builtin)), ); }; } fn panic_handler(f: impl Fn() + RefUnwindSafe) { loop { let result = catch_unwind(&f).unwrap_err(); eprintln!("{result:?}"); } } fn delsh_loop() { let mut interpreter = Interpreter::new(); interpreter.set_atom("T".into(), delsh::builtins::T.clone()); interpreter.set_atom("F".into(), delsh::builtins::F.clone()); interpreter.set_atom("NIL".into(), delsh::builtins::NIL.clone()); add_builtin!(interpreter, "atom?", is_atom); add_builtin!(interpreter, "equal?", is_equal); add_builtin!(interpreter, "==", is_equal); add_builtin!(interpreter, "nil?", is_nil); add_builtin!(interpreter, "member?", is_member); add_builtin!(interpreter, "less?", is_less); add_builtin!(interpreter, "<", is_less); add_builtin!(interpreter, "greater?", is_greater); add_builtin!(interpreter, ">", is_greater); add_builtin!(interpreter, "zero?", is_zero); add_builtin!(interpreter, "one?", is_one); add_builtin!(interpreter, "negative?", is_negative); add_builtin!(interpreter, "number?", is_number); add_builtin!(interpreter, "int?", is_int); add_builtin!(interpreter, "+", plus); add_builtin!(interpreter, "add", plus); add_builtin!(interpreter, "-", minus); add_builtin!(interpreter, "sub", minus); add_builtin!(interpreter, "subtract", minus); add_builtin!(interpreter, "difference", minus); add_builtin!(interpreter, "*", times); add_builtin!(interpreter, "mul", times); add_builtin!(interpreter, "multiply", times); add_builtin!(interpreter, "/", divide); add_builtin!(interpreter, "%", remainder); add_builtin!(interpreter, "**", expt); add_builtin!(interpreter, "if", if_function); add_builtin!(interpreter, "while", while_function); add_builtin!(interpreter, "loop", loop_function); add_builtin!(interpreter, "do", do_function); add_builtins!(interpreter => car cdr cons); add_builtins!(interpreter => car cdr cons ff ); add_builtins!(interpreter => cadr cdar caar cddr); add_builtins!(interpreter => caaar caadr cadar caddr cdaar cdadr cddar cdddr); add_builtins!(interpreter => first second third fourth fifth sixth seventh eighth ninth tenth); add_builtins!(interpreter => and or not); add_builtins!(interpreter => pair assoc subst sublis); add_builtins!(interpreter => list reverse append length efface intersection union); add_builtins!(interpreter => defun lambda maplist); add_builtins!(interpreter => plus minus negate times add1 sub1 max min recip quotient remainder divide expt sqrt); add_builtins!(interpreter => quote set eval apply); interpreter.set_atom( "SEND-MESSAGE".into(), Arc::new(Value::RustFn(|interpreter, args| { let mut key = ThreadKey::get().unwrap(); let program = args[0].string().unwrap().parse::().unwrap(); let fields = args .iter() .skip(1) .map(|arg| match &*interpreter.eval(arg.clone()) { Value::Identifier(_) | Value::RustFn(_) | Value::DelshFn { .. } | Value::Pair(..) => MessageField::Empty, Value::Number(number) => { MessageField::Bytes(number.to_string().into_bytes().into()) } Value::String(string) => MessageField::Bytes(string.as_bytes().into()), }); let message = Message::new(&mut key, fields.collect::>()); let response = send_message(&mut key, program, message); let response = response.wait(); match response.unwrap() { MessageField::Empty => delsh::builtins::NIL.clone(), MessageField::Bytes(bytes) => { Arc::new(Value::String(String::from_utf8_lossy(bytes).into())) } MessageField::File(_) => todo!(), } })), ); let mut buffer = String::new(); let stdin = std::io::stdin(); loop { buffer.clear(); print!("$ "); std::io::stdout().flush().unwrap(); stdin.read_line(&mut buffer).unwrap(); let mut lexer = delsh::tokens::Lexer::new(&buffer).peekable(); let program = delsh::ast::parse_program(&mut lexer).unwrap(); for command in &*program.commands { let value = interpreter.run_ast_command(command); println!("{value:?}"); } } } pub fn delsh(key: ThreadKey, channel: Receiver) { drop(key); drop(channel); panic_handler(delsh_loop); }