SupervisionTree

Inherits from Value

SupervisionTree — a navigable snapshot of the live supervision tree (ADR 0092).

A SupervisionTree is a thin, immutable wrapper over a flat List(SupervisionNode) plus the parent/child adjacency captured at snapshot time. It is the high-level view layered on the flat records: the full collection protocol (do:, select:, detect:, collect:) plus tree navigation (root, nodesOfKind:, findClass:). Reach one via ProcessNavigation default tree or the Workspace processes alias.

The snapshot is best-effort point-in-time: iterating a tree never re-enters OTP (it is frozen), so the walk is internally consistent. To observe change, take a new snapshot.

Examples

tree := ProcessNavigation default tree
tree root                          // => the snapshot root SupervisionNode
tree size                          // => total node count
tree do: [:node | Transcript showLine: node printString]
tree select: [:node | node isSupervisor]
tree nodesOfKind: #beamtalkActor   // => List(SupervisionNode)
tree findClass: Counter            // => List(SupervisionNode) for Counter actors

Instance Methods

nodes source

The flat list of nodes, each enriched so parent/child navigation works.

This is the flat record API the ADR exposes; root is the navigable head layered on top.

Examples

tree nodes   // => #(a SupervisionNode, ...)
root source

The snapshot root — the first node with no parent — or nil for an empty snapshot.

Note: the default / system snapshot can be a forest (the app root, workspace-attached supervisors, and standalone supervised trees are each parentless). root returns the first such root; iterate nodes (or select: [:n | n parentPid isNil]) to reach every root in a forest.

Examples

tree root   // => a SupervisionNode | nil
size source

Total number of nodes in the snapshot.

Examples

tree size   // => 6
isEmpty source

Whether the snapshot is empty.

Examples

tree isEmpty   // => false
do: aBlock source

Pre-order walk: evaluate aBlock for every node in the snapshot.

Examples

tree do: [:node | Transcript showLine: node printString]
select: aBlock source

The nodes for which aBlock answers true.

Examples

tree select: [:node | node isSupervisor]
detect: aBlock source

The first node for which aBlock answers true. Raises if none match — use detect:ifNone: for a default.

Examples

tree detect: [:node | node registeredName == #DatabasePool]
detect: aBlock ifNone: noneBlock source

The first node for which aBlock answers true, or the value of noneBlock if none match.

Examples

tree detect: [:n | n isSupervisor] ifNone: [nil]
collect: aBlock source

Collect the result of applying aBlock to every node.

Examples

tree collect: [:node | node registeredName]
nodesOfKind: aKind source

The nodes whose kind equals aKind (e.g. #beamtalkActor, #otpProcess).

Examples

tree nodesOfKind: #beamtalkActor   // => List(SupervisionNode)
findClass: aClass source

The nodes backed by the Beamtalk class aClass — every running instance of that class in the supervision tree.

Examples

tree findClass: Counter   // => List(SupervisionNode) for Counter actors
asDictionaries source

A serialisable form of the snapshot — one Dictionary per node carrying its identity, kind, class, child count, and parent linkage (adjacency).

This is the cross-surface wire form (ADR 0092 Implementation §5): the MCP and LiveView/browser surfaces render this structure so every surface shows equivalent data. Pids are rendered as Strings (JSON-stable); parentPid reconstructs the tree.

Examples

ProcessNavigation default tree asDictionaries
// => #(#{#pid => "<0.200.0>", #kind => #beamtalkSupervisor, ...}, ...)
printString source

Human-readable summary, e.g. #SupervisionTree<6 nodes, root: #AppSup> or #SupervisionTree<empty>.

Examples

Workspace processes printString   // => "#SupervisionTree<3 nodes, root: #AppSup>"

Inherited Methods

From Value

printString

Return a developer-readable string representation showing fields.

Produces ClassName(field: value, ...) via the canonical structural renderer (ADR 0094). Field values are rendered with their own printString (strings stay quoted, nested values show their structural form), in sorted field order. A class with no fields produces ClassName(). Recursion is bounded by depth/width/length caps with a cycle guard.

Examples

ValuePoint x: 3 y: 4        printString   // => "ValuePoint(x: 3, y: 4)"
ValuePoint new              printString   // => "ValuePoint(x: 0, y: 0)"

From Object

class

Return the class of the receiver.

Examples

42 class              // => Integer
"hello" class         // => String
isNil

Test if the receiver is nil. Returns false for all objects except nil.

Examples

42 isNil              // => false
nil isNil             // => true
notNil

Test if the receiver is not nil. Returns true for all objects except nil.

Examples

42 notNil             // => true
nil notNil            // => false
ifNil: _nilBlock

If the receiver is nil, evaluate nilBlock. Otherwise return self.

Examples

42 ifNil: [0]         // => 42
nil ifNil: [0]        // => 0
ifNotNil: notNilBlock

If the receiver is not nil, evaluate notNilBlock with self.

Examples

42 ifNotNil: [:v | v + 1]   // => 43
nil ifNotNil: [:v | v + 1]  // => nil
ifNil: _nilBlock ifNotNil: notNilBlock

If nil, evaluate nilBlock; otherwise evaluate notNilBlock with self.

Examples

42 ifNil: [0] ifNotNil: [:v | v + 1]    // => 43
nil ifNil: [0] ifNotNil: [:v | v + 1]   // => 0
ifNotNil: notNilBlock ifNil: _nilBlock

If not nil, evaluate notNilBlock with self; otherwise evaluate nilBlock.

Examples

42 ifNotNil: [:v | v + 1] ifNil: [0]    // => 43
nil ifNotNil: [:v | v + 1] ifNil: [0]   // => 0
printString

Return the developer-readable (Debug) string representation.

printString is the Debug protocol (ADR 0094): the self-describing, structural form used by the REPL, logs, and by any other printString that nests this object. It is the REPL default — evaluating an expression shows its printString.

This default returns the bare class name (no a/an article — the old "a ClassName" form was dropped in ADR 0094). Value overrides it with the structural ClassName(field: value, ...) form, actors render as Actor(ClassName, pid), supervisors as Supervisor(ClassName, pid) / DynamicSupervisor(ClassName, pid), and primitive types (Integer, String, List, …) override it with their own richer output. Authors rarely override printString directly — the default is derived.

Examples

42 printString            // => "42"
displayString

Return the user-facing (Display) string representation.

displayString is the Display protocol (ADR 0094): the human-facing form. It is the hook the language pulls during string interpolation — every {...} segment renders via the value's displayString. Developers rarely call it directly; they override it when a value has a natural human rendering (e.g. Money$10.50, where printString would still show the Debug form).

It defaults to printString, so most types need no override. String and Symbol demonstrate the split: "hi" printString"\"hi\"" (quoted, Debug) while "hi" displayString"hi" (plain, Display); likewise #foo drops its # prefix under displayString.

displayString is not part of the Printable protocol (deferred per ADR 0094 §5).

Examples

42 displayString             // => "42"
inspect

Open a navigable Inspector cursor on the receiver.

ADR 0095 Phase 3 (BT-2504). inspect is repurposed from -> String (the ADR-0094 deferral) to the verb that produces an Inspector — a live, immutable cursor for drilling into the object (Inspector on: self). anObject inspect is the shorthand; Inspector on: anObject is the explicit spelling. The cursor exposes fields/at:/path/refresh/ printString (an indented text tree) and asDictionaries (the MCP/browser wire form); see Inspector.

This is a breaking change: code that used inspect for its old String result must switch to printString (the structural Debug string, ADR 0094) — a transitional lint flags inspect used directly in ++/ string position.

Examples

42 inspect kind                  // => #value
(Point x: 3 y: 4) inspect fields size   // => 2
(Point x: 3 y: 4) printString    // => "Point(x: 3, y: 4)"  (the old inspect string)
yourself Sealed

Return the receiver itself. Useful for cascading side effects.

Examples

42 yourself            // => 42
hash

Return a hash value for the receiver.

Examples

42 hash
respondsTo: selector Sealed

Test if the receiver responds to the given selector.

Examples

42 respondsTo: #abs    // => true
fieldNames Sealed

Return the names of fields.

Examples

42 fieldNames             // => #()
fieldAt: name Sealed

Return the value of the named field.

Examples

object fieldAt: #name
fieldAt: name put: value Sealed

Set the value of the named field (returns new state).

Examples

object fieldAt: #name put: "Alice"
perform: selector Sealed

Send a unary message dynamically.

Examples

42 perform: #abs       // => 42
perform: selector withArguments: args Sealed

Send a message dynamically with arguments.

Examples

3 perform: #max: withArguments: #(5)   // => 5
subclassResponsibility

Raise an error indicating this method must be overridden by a subclass.

Examples

self subclassResponsibility
notImplemented

Raise an error indicating this method has not yet been implemented.

Use this for work-in-progress stubs. Distinct from subclassResponsibility, which signals an interface contract violation.

Examples

self notImplemented
show: aValue

Send aValue to the current transcript without a trailing newline.

Nil-safe: does nothing when no transcript is set (batch compile, tests).

Examples

42 show: "value: "
showCr: aValue

Send aValue to the current transcript followed by a newline.

Nil-safe: does nothing when no transcript is set (batch compile, tests).

Examples

42 showCr: "hello world"
isKindOf: aClass

Test if the receiver is an instance of aClass or any of its subclasses.

For class-object receivers, follows Smalltalk semantics: self class is the metaclass, so the check walks the parallel metaclass hierarchy. The parallel chain is grounded at ProtoObject class superclass == Class (ADR 0036), so the metaclass tower merges into the instance-side Class → Behaviour → Object → ProtoObject chain. As a result, Integer isKindOf: Object and Integer isKindOf: Class both return true.

Examples

42 isKindOf: Integer        // => true
42 isKindOf: Object         // => true
#foo isKindOf: Symbol       // => true
#foo isKindOf: String       // => false
Integer isKindOf: Number    // => false (metaclass chain, not instance chain)
Integer isKindOf: Number class  // => true  (Number class is in the parallel chain)
Integer isKindOf: Object    // => true (grounded — Object is reachable via the metaclass tower)
Integer isKindOf: Class     // => true (Integer class inherits from Class)
error: message

Raise an error with the given message.

Examples

self error: "something went wrong"
delegate Sealed

Delegate message dispatch to the backing Erlang module (ADR 0101, BT-2720).

This method is a sentinel — a plain Object has no backing Erlang module, so calling delegate raises an Error at runtime. Stateless Objects declared with native: have their self delegate method bodies rewritten by the compiler's codegen phase to call the backing module directly, so the sentinel is never reached on a native: class.

Unlike Actor's delegate (visible only to Actor subclasses), this Object-base sentinel is visible to every class, so delegate is a reserved selector on the Object protocol.

Examples

42 delegate   // => ERROR: delegate called on a non-native Object

From ProtoObject

== other

Test value equality (Erlang ==).

Examples

42 == 42           // => true
"abc" == "abc"     // => true
/= other

Test value inequality (negation of ==).

Examples

1 /= 2             // => true
42 /= 42           // => false
class

Return the class of the receiver.

Examples

42 class            // => Integer
"hello" class       // => String
doesNotUnderstand: selector args: arguments

Handle messages the receiver does not understand. Override for custom dispatch.

Examples

42 unknownMessage   // => ERROR: does_not_understand
perform: selector withArguments: arguments

Send a message dynamically with an arguments list.

Examples

42 perform: #abs withArguments: #()   // => 42
performLocally: selector withArguments: arguments

Execute a class method in the caller's process, bypassing gen_server dispatch.

The caller takes responsibility for knowing the method does not mutate class state. Useful for long-running class methods that would otherwise block the class object's gen_server.

Limitations: only resolves methods defined directly on the target class module (does not walk the superclass chain). Class variables and self are not available to the method (nil and #{} are passed).

Examples

MyClass performLocally: #run:ctx: withArguments: #(input, ctx)
perform: selector withArguments: arguments timeout: timeoutMs

Send a message dynamically with an arguments list and explicit timeout.

The timeout (in milliseconds or #infinity) applies to the gen_server:call when the receiver is an actor. For value types, timeout is ignored.

Examples

actor perform: #query withArguments: #(sql) timeout: 30000