From a38a686a76cbd30f014f3d23768bde0feef93ec3 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Sat, 5 Jul 2025 14:39:17 -0400 Subject: [PATCH] revert `spawn!` as a special form --- may_2025_thoughts.md | 31 +++++++++++++++++++++++++++++++ src/lexer.rs | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/may_2025_thoughts.md b/may_2025_thoughts.md index 4a37c12..0c3eb36 100644 --- a/may_2025_thoughts.md +++ b/may_2025_thoughts.md @@ -1208,3 +1208,34 @@ After that: - [x] read inputs? - [x] load url text? +### Following links +#### 2025-07-05 +Doing some last minute design work on linking processes. +Here's the erlang way: +* `link` is `link/1`: we always link _from a process_. +* links are always bidirectional +* [ ] update the link API to reflect this +* There's the concept of an exit signal + - erlang has three ways of doing this (ish): `:normal` (returning), `:kill` (panic), or a reason (which is a value). + - you can "trap" an exit signal that's `:normal` or a reason, but not if it's `:kill`, which will bring down the monitoring process +* I think in ludus we want... + +Well? What do we want? + +Erlang and Elixir have designs that are meant for massively concurrent processes. +In addition, I've been thinking about how the willy-nilly, anything goes, messages getting passed around all kinds of places, actually cuts against the spirit of Ludus. +What sort of process management, abstraction, modelling, and mental-modelling do we want in ludus? +My sense is that, actually, I have to build the things we're going to build before I have a sense of what needs doing. +`link` may not even be a thing we need? + +Anyway, here's the tl;dr for basic process linking: +* `link/1` should establish a bidirectional link, bringing one process down if the other exits for any reason, causing a panic if the linked process exits unexpectedly, even on a normal return +* `monitor/1` means we can monitor exit messages, these will be `(:exit, pid, (:ok, value))` in the case of successful return, or `(:exit, pid, (:err, msg))` in the case of a panic. These are sent as normal messages to the monitoring process. + +Erlang/Elixir has a lot more, but that's basically it for Ludus for now. +`monitor/1` makes it easy to write an `await`. + +As I'm thinking about this, I actually want to roll back `spawn` as a special form. +I think it's actually a good cognitive shift to understand that functions are reified, deferred computations. +And that processes take this a long way. +We can revisit the idea of a special spawn form later. diff --git a/src/lexer.rs b/src/lexer.rs index a16d4f0..c9090d6 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -76,7 +76,7 @@ pub fn lexer( "nil" => Token::Nil, // todo: hard code these as type constructors "as" | "box" | "do" | "else" | "fn" | "if" | "let" | "loop" | "match" | "panic!" - | "recur" | "repeat" | "then" | "when" | "with" | "or" | "and" | "receive" | "spawn!" => { + | "recur" | "repeat" | "then" | "when" | "with" | "or" | "and" | "receive" => { Token::Reserved(word) } _ => Token::Word(word),