Compare commits

...

2 Commits

Author SHA1 Message Date
Scott Richmond
a444f789f3 add new actor functions 2025-07-06 19:40:55 -04:00
Scott Richmond
842f1e7634 release build 2025-07-06 19:06:27 -04:00
5 changed files with 57 additions and 5 deletions

View File

@ -1049,6 +1049,15 @@ fn send {
fn spawn! { fn spawn! {
"Spawns a process. Takes a 0-argument (nullary) function that will be executed as the new process. Returns a keyword process ID (pid) of the newly spawned process." "Spawns a process. Takes a 0-argument (nullary) function that will be executed as the new process. Returns a keyword process ID (pid) of the newly spawned process."
(f as :fn) -> {
let new_pid = base :process (:spawn, f)
link! (new_pid)
new_pid
}
}
fn fledge! {
"Spawns a process and then immediately unlinks from it. Takes a 0-argument (nullary) function that will be executed as the new process. Returns a keyword process ID (pid) of the newly fledged process."
(f as :fn) -> base :process (:spawn, f) (f as :fn) -> base :process (:spawn, f)
} }
@ -1067,6 +1076,11 @@ fn link! {
(pid as :keyword) -> base :process (:link, pid) (pid as :keyword) -> base :process (:link, pid)
} }
fn unlink! {
"Unlinks this process from the other process."
(pid as :keyword) -> base :process (:unlink, pid)
}
fn monitor! { fn monitor! {
"Subscribes this process to another process's exit signals. There are two possibilities: a panic or a return. Exit signals are in the form of `(:exit, pid, (:ok, value)/(:err, msg))`." "Subscribes this process to another process's exit signals. There are two possibilities: a panic or a return. Exit signals are in the form of `(:exit, pid, (:ok, value)/(:err, msg))`."
(pid as :keyword) -> base :process (:monitor, pid) (pid as :keyword) -> base :process (:monitor, pid)
@ -1092,6 +1106,19 @@ fn await! {
panic! "Monitored process {pid} panicked with {msg}" } panic! "Monitored process {pid} panicked with {msg}" }
} }
} }
(pids as :list) -> {
each! (pids, monitor!)
fold (
(fn (results, pid) -> append (results, await! (pid)))
pids
[]
)
}
}
fn hibernate! {
"Ensures the current process will never return, allowing other processes to do their thing indefinitely. Does not unlink the process, so panics in linked processes will still bubble up."
() -> receive { _ -> hibernate! () }
} }
fn heed! { fn heed! {
@ -1487,6 +1514,8 @@ fn key_pressed? {
monitor! monitor!
await! await!
heed! heed!
unlink!
hibernate!
spawn_turtle! spawn_turtle!

View File

@ -403,7 +403,7 @@ function __wbg_get_imports() {
_assertBoolean(ret); _assertBoolean(ret);
return ret; return ret;
}; };
imports.wbg.__wbindgen_closure_wrapper8189 = function() { return logError(function (arg0, arg1, arg2) { imports.wbg.__wbindgen_closure_wrapper8194 = function() { return logError(function (arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 363, __wbg_adapter_20); const ret = makeMutClosure(arg0, arg1, 363, __wbg_adapter_20);
return ret; return ret;
}, arguments) }; }, arguments) };

Binary file not shown.

View File

@ -117,7 +117,7 @@ pub fn words(str: &Value) -> Value {
let mut words = Vector::new(); let mut words = Vector::new();
let mut word = String::new(); let mut word = String::new();
for char in str.chars() { for char in str.chars() {
if char.is_alphanumeric() { if char.is_alphanumeric() || char == '\'' {
word.push(char) word.push(char)
} else if !word.is_empty() { } else if !word.is_empty() {
words.push_back(Value::from_string(word)); words.push_back(Value::from_string(word));

View File

@ -292,9 +292,10 @@ impl Creature {
// console_log!("sending exit signal {exit_signal}"); // console_log!("sending exit signal {exit_signal}");
self.send_msg(Value::Keyword(pid), exit_signal); self.send_msg(Value::Keyword(pid), exit_signal);
} }
for pid in self.siblings.clone() { // returns no longer kill siblings
self.zoo.borrow_mut().kill(pid); // for pid in self.siblings.clone() {
} // self.zoo.borrow_mut().kill(pid);
// }
} }
// TODO: fix these based on what I decide about `link` & `monitor` // TODO: fix these based on what I decide about `link` & `monitor`
@ -304,6 +305,7 @@ impl Creature {
unreachable!("expected keyword pid in monitor"); unreachable!("expected keyword pid in monitor");
}; };
if other != self.pid { if other != self.pid {
self.unlink(Value::Keyword(other));
let mut other = self.zoo.borrow_mut().catch(other); let mut other = self.zoo.borrow_mut().catch(other);
other.parents.push(self.pid); other.parents.push(self.pid);
self.zoo.borrow_mut().release(other); self.zoo.borrow_mut().release(other);
@ -312,6 +314,26 @@ impl Creature {
self.push(Value::Keyword("ok")); self.push(Value::Keyword("ok"));
} }
fn delete_from_siblings(&mut self, other: &'static str) {
let idx = self.siblings.iter().position(|pid| other == *pid);
if let Some(idx) = idx {
self.siblings.swap_remove(idx);
}
}
fn unlink(&mut self, other: Value) {
let Value::Keyword(other) = other else {
unreachable!("expected keyword pid in unlink")
};
if other != self.pid {
self.delete_from_siblings(other);
let mut other = self.zoo.borrow_mut().catch(other);
other.delete_from_siblings(self.pid);
self.zoo.borrow_mut().release(other);
}
self.push(Value::Keyword("ok"))
}
fn link(&mut self, other: Value) { fn link(&mut self, other: Value) {
let Value::Keyword(other) = other else { let Value::Keyword(other) = other else {
unreachable!("expected keyword pid in link"); unreachable!("expected keyword pid in link");
@ -359,6 +381,7 @@ impl Creature {
} }
"link" => self.link(args[1].clone()), "link" => self.link(args[1].clone()),
"monitor" => self.monitor(args[1].clone()), "monitor" => self.monitor(args[1].clone()),
"unlink" => self.unlink(args[1].clone()),
"flush" => { "flush" => {
let msgs = self.mbx.iter().cloned().collect::<Vec<_>>(); let msgs = self.mbx.iter().cloned().collect::<Vec<_>>();
let msgs = Vector::from(msgs); let msgs = Vector::from(msgs);