diff options
| author | Mica White <botahamec@outlook.com> | 2025-12-07 14:23:22 -0500 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2025-12-07 14:23:22 -0500 |
| commit | 610e575043bfc75feafcce5bddaf7e1a436e5d02 (patch) | |
| tree | 15149b937984f73feb7bb63be662882094f27abe /src/builtins/delsh.rs | |
Diffstat (limited to 'src/builtins/delsh.rs')
| -rw-r--r-- | src/builtins/delsh.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/builtins/delsh.rs b/src/builtins/delsh.rs new file mode 100644 index 0000000..6c9883c --- /dev/null +++ b/src/builtins/delsh.rs @@ -0,0 +1,136 @@ +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); +} |
