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::<Uuid>().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::<Box<_>>());
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<Message>) {
drop(key);
drop(channel);
panic_handler(delsh_loop);
}
|