WorkspaceInterface
WorkspaceInterface — Per-workspace actor introspection and binding container.
Modeled on Squeak 5.2+'s Environment class: a scoped container for
workspace-level bindings and actor introspection. Each workspace has its
own WorkspaceInterface instance.
The singleton instance is set during workspace bootstrap (ADR 0019 Phase 2).
The convenience binding Workspace is also available after bootstrap.
Examples
WorkspaceInterface current actors
WorkspaceInterface current actorAt: "<0.132.0>"
WorkspaceInterface current actorsOf: Counter
Methods
- class » current
- actors
- processes
- actorAt: pidString
- actorsOf: aClass
- classes
- testClasses
- globals
- currentSession
- sessions
- sync
- changes
- load: path
- newClass: source at: path
- flush
- flush: filter
- test
- test: testClass
- bind: value as: bindingName
- unbind: bindingName
- supervisor
- startSupervisor: aClass
- stopSupervisor: aClass
- supervisors
- autoflush
- autoflush: enabled
- dependencies
Class Methods
Return the current singleton instance.
Instance Methods
Return a list of all live actors as object references.
Examples
Workspace actors
Return a navigable snapshot of the live supervision tree (ADR 0092).
The dynamic counterpart of Workspace actors: a SupervisionTree over the
workspace application tree with runtime plumbing filtered out (the
default scope, == ProcessNavigation default tree). Walk it (do:,
select:, findClass:), reach the head (root), or take the flat record
list (nodes). The snapshot is best-effort point-in-time — re-call to
refresh.
The default-scope reach is an ADR-0091 Read op, scoped exactly like
actors. For the privileged whole-node view use ProcessNavigation system tree.
Examples
Workspace processes root // => the snapshot root SupervisionNode
Workspace processes do: [:n | Transcript showLine: n printString]
Workspace processes findClass: Counter // => List(SupervisionNode)
Workspace processes nodes // => the flat List(SupervisionNode)
Look up a specific actor by pid string.
Examples
Workspace actorAt: "<0.132.0>"
Return all actors of a given class.
Examples
Workspace actorsOf: Counter
Return a list of loaded user classes with source file info.
Examples
Workspace classes
Return classes that are TestCase subclasses.
Examples
Workspace testClasses
Return a live BindingsView over the project namespace (ADR 0081).
Reads reflect the current workspace singletons (Transcript, Beamtalk,
Workspace) and user-registered bindings (bind:as:). It is the same
BindingsView type as Session current bindings, so both binding layers
share one Dictionary protocol (at:, at:put:, removeKey:,
includesKey:, keys, values, size, do:).
Writes are synchronous: at:put: routes through bind:as: and
removeKey: through unbind:, inheriting their protected-name conflict
checks. (Beamtalk globals — the class registry — stays a Dictionary;
it is not a mutable binding layer.)
Examples
Workspace globals at: #Transcript // => the Transcript singleton
Workspace globals includesKey: #Beamtalk // => true
Return the calling session as a Session, or nil outside a REPL eval
(ADR 0081 Phase 5).
A navigation alias for Session current: it returns the identical value
(the same Session carrying this session's id and bindings, or nil when
there is no session — e.g. compiled program code). There is no hasSession
predicate; guard with Workspace currentSession isNil or
Session current ifNotNil: [:s | ...].
Examples
Workspace currentSession // => a Session (in REPL) | nil
Workspace currentSession isNil // => false (in REPL)
Return a List of Session values, one per live shell (ADR 0081 Phase 7).
Each value is minted the same way Session withId: does, so it works with
the instance reads (s id, s bindings keys) and rejects cross-session
writes. This closes the gap left by Session withId: (which assumes you
already know the id): tooling discovers live session ids with
Workspace sessions collect: [:s | s id].
Examples
Workspace sessions // => #(a Session)
Workspace sessions collect: [:s | s id] // => #("user-repl-abc-123")
Sync the project: incrementally compile all changed files.
Scans the current working directory for a beamtalk.toml project
manifest, then finds .bt and .erl files, compiles changed files
in dependency order, and returns a result Dictionary.
The result Dictionary contains:
#summary— human-readable summary String#classes— List of loaded class name Strings#errors— List of error Dictionaries (empty on success)#changedCount— number of files reloaded#unchangedCount— number of unchanged files#deletedCount— number of deleted files
Examples
Workspace sync // => #{#summary => "Reloaded 2 of 5 files (3 unchanged)", ...}
(Workspace sync) at: #summary // => "Reloaded 2 of 5 files (3 unchanged)"
Return the workspace ChangeLog — the navigable view of pending in-memory changes (ADR 0082).
All pending-state queries live on the returned ChangeLog object, following
Pharo's Smalltalk changes idiom: "is anything dirty?" is
Workspace changes notEmpty; "what's dirty?" is
Workspace changes dirtyMethods.
Examples
Workspace changes notEmpty // => false
Workspace changes dirtyMethods // => #{}
Compile and load a .bt file, registering the class. Returns a List of loaded class objects (empty if none resolved). Returns a structured error if path is not a String or the file cannot be loaded.
Examples
Workspace load: "examples/counter.bt" // => [Counter]
Create a brand-new class from a source String at a target path (ADR 0082).
Compiles and installs the class in memory, then records a durable
kind: #'new-class' ChangeLog entry. Phase 1 does NOT write the file to
disk — that happens later on Workspace flush, which replays the entry to
write the initial file. Returns the loaded class object(s), like load:.
Raises a loud, specific error (no silent fallback) when:
pathalready exists on disk;pathlies outside the project source tree;- the declared class name does not match the basename of
path(one class per file, ADR 0040); - a class of that name is already loaded (use
compile:source:instead).
Examples
Workspace newClass: "Object subclass: Greeter" at: "src/greeter.bt"
// => [Greeter]
Flush every pending durable change to disk (ADR 0082 Phase 2).
Writes each pending ChangeLog entry's patched body back to its source
file via byte-span splice (trivia-preserving — no AST reprint), atomically
(<file>.tmp + atomic rename), with external-edit conflict detection.
Returns a FlushResult summary recording what was written, what was
skipped, and what conflicted:
flushed(Integer) — number of durable entries writtenfiles(List of String) — files written, in rename ordernewClasses(Integer) — subset offlushedfor new-class entriesconflicts(List) — per-file conflict descriptors (#external_edit,#target_exists,#span_out_of_range, ...). A non-empty list means the listed entries remain pending and require manual reconciliation.
Quiet on success; loud only on conflicts and structured errors.
Examples
Workspace flush // => _ (flush summary)
Flush the pending ChangeLog entries matching filter (ADR 0082 Phase 2).
filter is one of:
- a Class — flush only entries targeting that class
- a Symbol (e.g.
#'new-class') — flush only entries of that kind - a Dictionary
#{#file => "path"}— flush only entries against that source file
Returns the same FlushResult shape as flush.
Examples
Workspace flush: Counter // => _
Workspace flush: #'new-class' // => _
Workspace flush: #{ #file => "src/counter.bt" } // => _
Run all loaded test classes and return a TestResult.
Examples
Workspace test
Run a specific test class and return a TestResult.
Examples
Workspace test: CounterTest
Register a value in the workspace namespace under a given name. Subsequent REPL evals can reference the value by name. Raises an error if name exists in Beamtalk globals (system name conflict). Warns if name is an existing loaded class (use reload instead).
Examples
Workspace bind: myActor as: #MyTool
Remove a registered name from the workspace namespace. Raises an error if name is not found.
Examples
Workspace unbind: #MyTool
Return the OTP application root supervisor, or nil if not configured.
Returns the Supervisor instance registered when a package with
[application] supervisor = "ClassName" starts. Returns nil if the
application has not been started with an OTP supervisor root.
Examples
Workspace supervisor // => Supervisor(AppSup, 0.200.0)
Workspace supervisor children // => #(#DatabasePool #HTTPRouter)
Start and attach a supervisor to the workspace supervision tree.
The class must be a Supervisor or DynamicSupervisor subclass. Idempotent: returns the existing instance if already attached. Supports iterative development — stop and re-attach after reloading.
Examples
Workspace startSupervisor: MySup // => Supervisor(MySup, 0.200.0)
Workspace startSupervisor: MySup // => Supervisor(MySup, 0.200.0) (idempotent)
Stop and remove a supervisor from the workspace.
Works for both workspace-attached supervisors and the root application supervisor. Cleanly shuts down the supervisor and all its children. Raises an error if the supervisor is not running or not visible.
Examples
Workspace stopSupervisor: MySup // => nil
List all supervisors visible from the workspace.
Returns the root application supervisor (if registered) and all
supervisors attached via startSupervisor:. The root supervisor
is not part of the workspace supervision tree but is included
for discoverability.
Examples
Workspace supervisors // => #(Supervisor(MySup, 0.200.0))
Read the autoflush workspace setting (ADR 0082 Phase 4).
Default is false. When true, every successful durable in-memory patch
(via >> / compile:source: / newClass:at:) immediately triggers a
Workspace flush after the install, collapsing the model to write-through
at the workspace level. The setting persists across workspace restarts.
Autoflush is best-effort: on flush failure (external-edit conflict, write error) memory and disk diverge and the ChangeEntry remains in the log for manual reconciliation — the BEAM module install is not rolled back (live actors may hold references to the new closures).
Examples
Workspace autoflush // => false
Set the autoflush workspace setting (ADR 0082 Phase 4).
enabled must be a Boolean. Persists to the workspace metadata.json so
the setting survives workspace restart. Returns the new value so the
caller can confirm the effective state.
Examples
Workspace autoflush: true // => true
Workspace autoflush: false // => false
Return a Dictionary of direct dependency packages for the current workspace.
Keys are package name Strings, values are Package objects. Returns an empty Dictionary if the workspace has no declared dependencies.
Examples
Workspace dependencies
// => _
Inherited Methods
From Object
Return the class of the receiver.
Examples
42 class // => Integer
"hello" class // => String
Test if the receiver is nil. Returns false for all objects except nil.
Examples
42 isNil // => false
nil isNil // => true
Test if the receiver is not nil. Returns true for all objects except nil.
Examples
42 notNil // => true
nil notNil // => false
If the receiver is nil, evaluate nilBlock. Otherwise return self.
Examples
42 ifNil: [0] // => 42
nil ifNil: [0] // => 0
If the receiver is not nil, evaluate notNilBlock with self.
Examples
42 ifNotNil: [:v | v + 1] // => 43
nil ifNotNil: [:v | v + 1] // => nil
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
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
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"
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"
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)
Return the receiver itself. Useful for cascading side effects.
Examples
42 yourself // => 42
Return a hash value for the receiver.
Examples
42 hash
Test if the receiver responds to the given selector.
Examples
42 respondsTo: #abs // => true
Return the names of fields.
Examples
42 fieldNames // => #()
Return the value of the named field.
Examples
object fieldAt: #name
Set the value of the named field (returns new state).
Examples
object fieldAt: #name put: "Alice"
Send a unary message dynamically.
Examples
42 perform: #abs // => 42
Send a message dynamically with arguments.
Examples
3 perform: #max: withArguments: #(5) // => 5
Raise an error indicating this method must be overridden by a subclass.
Examples
self subclassResponsibility
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
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: "
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"
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)
Raise an error with the given message.
Examples
self error: "something went wrong"
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
Test value equality (Erlang ==).
Examples
42 == 42 // => true
"abc" == "abc" // => true
Test value inequality (negation of ==).
Examples
1 /= 2 // => true
42 /= 42 // => false
Return the class of the receiver.
Examples
42 class // => Integer
"hello" class // => String
Handle messages the receiver does not understand. Override for custom dispatch.
Examples
42 unknownMessage // => ERROR: does_not_understand
Send a message dynamically with an arguments list.
Examples
42 perform: #abs withArguments: #() // => 42
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)
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