From 92d97c877391adf5734d43d5cb0af4fa79a5e4eb Mon Sep 17 00:00:00 2001
From: "Rph :3" <11350302+rphsoftware@users.noreply.github.com>
Date: Thu, 27 Mar 2025 18:54:01 +0100
Subject: [PATCH] Base for the actor system (just some docs)

---
 src/kernel/entry.lua  |   2 +
 src/kernel/system.lua | 117 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)
 create mode 100644 src/kernel/system.lua

diff --git a/src/kernel/entry.lua b/src/kernel/entry.lua
index 7474ba8..971d2e1 100644
--- a/src/kernel/entry.lua
+++ b/src/kernel/entry.lua
@@ -2,4 +2,6 @@
 -- this is responsible for initializing core kernel services
 -- required to advance to the next step of the OS
 
+require 'kernel.system'
+
 os.run({}, "/rom/programs/advanced/multishell.lua") -- placeholder
diff --git a/src/kernel/system.lua b/src/kernel/system.lua
new file mode 100644
index 0000000..bee8402
--- /dev/null
+++ b/src/kernel/system.lua
@@ -0,0 +1,117 @@
+--[[
+    The Erica Actor System ([Er]lang + A[kka])
+
+    Each actor has:
+    - Coroutine
+    - Mailbox
+    - Address
+    - Extra Addresses
+    - State
+    - Child IDs
+
+    The Actor System utilizes coroutine yielding for all invocations of the system. No global APIs are exposed by the system.
+    The following calls are available to actors:
+    - spawn function:handler table?:options
+        The options table exposes the following:
+        - addressBase   | default: seedocs | If not provided, the address will take this form: "$currentAddress/$childId" and childId gets incremented
+                                           | in local state. 
+                                           | If provided, the global address base counter gets updated and the provided address base is used.
+                                           | Actors created without an address base are considered child actors of the current actor,
+                                           | and their status updates (death) will emit status update events to the next immediate parent.
+                                           | The death of an actor will kill all of it's children recursively.
+        - localNamespace| default: nil     | If set, adds the localNamespace into the address of the newly spawned actor.
+        - extraAddresses| default: {}   | Logic for global base addresses, that are used to add receive-only extra addresses to this actor.
+        The returned value is: bStatus, tAddress?
+        - bStatus: True if successful, false if failed
+        - tAddress: Address of newly spawned actor
+    
+    - tell addressPredicate:string ...content
+        Any instances of `?` in addressPredicate are replaced with a random valid instance.
+        Adds a message of "content" to the mailbox of the target actor
+        The returned value is: bStatus, sData?
+        - bStatus: True if successful, false if failed
+        - sData: The error string if status is false, for example no valid instances.
+                 If status is true, actor address that received this tell.
+    
+    - announce addressPredicate:string ...content
+        Any instances of `?` in addressPredicate are replaced with all valid instances.
+        Adds a message of "content" to the mailbox of the target actor
+        The returned value is: bStatus, data?
+        - bStatus: True if successful, false if failed
+        - data:  The error string if status is false, for example no valid instances.
+                 If status is true, amount of actors that received this announcement.
+    
+    - ask addressPredicate:string timeout:number ...content
+        Suspends this actor until the responseHandle is used with the "reply" or "fail" syscall,
+        or until the timeout elapses. The timeout elapsing invalidates the handle and makes calls to "reply" or "fail" fail silently.
+        The return value is:
+        - bStatus: If the ask was successful
+        - ...data: If the status is false, this contains the reason for the error.
+                   If the status is true, the first value is the actor asked, and subsequent data contains the response from the actor asked.
+    
+    - reply askHandle:string ...data
+        Replies to an ask. Returns nil.
+    
+    - fail askHandle:string ...reason
+        Fails an ask. Returns nil.
+
+    - idle timeout:number receiveUnfiltered?:bool
+        Notifies the actor system that this actor is ready to process events. Values returned by this call are described below, in the signals section.
+        If receiveUnfiltered is set, the actor will receive "hostEvent" signals without any filtering.
+
+    Signals:
+    - timeout
+        When the idle call times out. No extra params
+    - message sourceAddress:string {content}
+        When a message is received from another actor.
+    - ask replyHandle:string sourceAddress:string {content}
+        When an ask is received from another actor. Good idea to immediately fail any asks that the current actor doesn't recognize.
+    - childStatus address:string {newStatus}
+        When a child's status updates (coroutine.status() call)
+    - hostEvent {data}
+        ComputerCraft event from the top level coroutine.yield() call. Use with caution, generally this should only be used by actors
+        that propagate events to announcement channels.
+
+    Addresses
+    There are 3 types of address:
+    - Fully Qualified Address
+    - Local Address
+    - Relative Address
+
+    Fully Qualified addresses take on the following format:
+        systemId .. ":/" .. localAddressWithinSystem
+
+        The purpose of fully qualified addresses is to be provided by the system to actors to have unambigous resolution of actors.
+        User-written code generally shouldn't need to use fully qualified addresses, because their primary use case is future compatibility
+        with a version of this system that allows multi-node operation (and setting wildcards on systemId)
+    
+    Local Addresses are full addresses within a single system.
+        The "child:" prefix is reserved in address parts only for automatically-generated addresses, and manual usage of it in addresses
+        is considered undefined behavior.
+
+        Here is an example address of the first actor spawned within the "com/colon-three/someApp" namespace:
+            "com/colon-three/someApp/1"  (subsequent actors are 2, 3, 4, etc. Monotonically increasing, but not guaranteed. Do not rely on this.)
+        
+        If that actor then makes a child, that child's address is:
+            "com/colon-three/someApp/1/child:1"
+        
+        And if that child makes another child, that child's address is:
+            "com/colon-three/someApp/1/child:1/child:1"
+        
+        If that actor makes a child with the local namespace of "someNs", the address will be:
+            "com/colon-three/someApp/1/someNs/child:2" (because child:1 for this actor already exists, and namespaces are for filtering only.)
+        
+        Every address of an actual actor ends with either a plain number, or the "child:number" template.
+
+    Relative Addresses:
+        Used only in calls, and taking the following format:
+            ".." - refer to the parent actor. IGNORES NAMESPACES!!!
+            "../someNs" - refer to parent actor's "someNs". Ignores the current actor's namespace.
+            "./someNs" - refer to the current actor's someNs namespace.
+
+        Allows asking the parent something, or the parent broadcasting something to all of it's children, or children in a specific namespace.
+        This is generally only useful with `?` in asks or broadcasts, because a child's ID shouldn't be considered predictable.
+]]
+
+local tActors = {}
+local tAddressBases = {}