Block

← Reference
Io

C implementation of Io blocks and methods (they share the same struct; block() binds a lexical scope, method() leaves scope NULL so activation uses the message target). IoBlockData carries the message tree, an argNames List, the optional captured scope, passStops (whether return/continue/break propagate to the caller), and profiler timing. Activation happens via IoBlock_activate, which is installed as the tag's activateFunc — any getSlot of an activatable Block thus runs the block without explicit message dispatch. IoBlock_activate builds a fresh locals object (cloned from state->localsProto), populates it with call/self/updateSlot plus the named arguments, and recursively evaluates the body via IoMessage_locals_performOn_. With frame-based coroutines and the iterative evaluator, that inner perform will usually redirect into the eval loop rather than recurse on the C stack. The optional profiler wraps IoBlock_activate with clock() bookkeeping.

IoBlock_activate(self, target, locals, m, slotContext)

Core block activation. Clones localsProto, falls back to the message target when no lexical scope was captured, creates a Call object via IoCall_with, and seeds the fresh locals with call/self/updateSlot. Arguments are pre-evaluated in the caller's locals (IoMessage_locals_ valueArgAt_) then bound by name, which is why blocks can see their sender's scope. The body is evaluated via IoMessage_locals_performOn_ — under the iterative evaluator this redirects into the frame state machine rather than recursing on the C stack. On return, if passStops is clear, the block's return/continue/break status propagates through state->returnValue/stopStatus. The IO_BLOCK_LOCALS_RECYCLING path manually frees the Call and blockLocals when neither got captured, reclaiming the common case immediately instead of waiting for GC.

IoBlock_activateWithProfiler(self, target, locals, m, slotContext)

Profiler-enabled wrapper around IoBlock_activate. setProfilerOn(true) swaps this in as the tag's activateFunc so every activation of this block accumulates elapsed clock() time into profilerTime.

IoBlock_copy_(self, other)

Shallow-copies another Block's message, argument names, and captured scope into self. Used by the commented-out BStream readFromStream to graft parsed code onto a freshly allocated Block; kept live because store/persistence work may re-enable it.

IoBlock_free(self)

Registered as the tag's freeFunc. Frees the argNames basekit List and the IoBlockData payload. The message tree is GC-managed.

IoBlock_justCode(self)

Serializes a Block to its Io source form as a UArray: opens with "block(" (lexical closure) or "method(" (dynamic) depending on whether a scope was captured, then emits the argument names and the message chain description. Caller owns the returned UArray.

IoBlock_mark(self)

Registered as the tag's markFunc. Marks the message tree (always present), the optional captured scope, and every argument name symbol.

IoBlock_message_(self, m)

Setter used by IoBlock_method and setMessage; IOREFs through the Block so the new message tree stays live.

IoBlock_method(target, locals, m)

Implementation of Object method(...). Allocates a fresh Block, takes the last argument of m as the body message and the rest as arg name symbols, and marks the Block as activatable (so slot lookup will auto-invoke it). Object block() calls this first and then sets scope to the sender's locals to convert it into a lexical closure.

IoBlock_new(state)

Convenience constructor: looks up the registered proto and clones it. Used by IoBlock_method (the backing implementation of method() and block()).

IoBlock_newTag(state)

Builds the Block tag with clone/mark/free function pointers plus the activateFunc that makes a Block self-executing when fetched from an activatable slot. The activateFunc is the key hook — IoCFunction uses the same mechanism.

IoBlock_proto(state)

Creates the Block proto: allocates an IoBlockData with a nil message, empty argNames list, and NULL scope, attaches the tag from IoBlock_newTag, and registers the Io-visible method table (print, code, message, argumentNames, setScope, call, performOn, passStops, profiler). All later Blocks and methods are clones of this proto.

IoBlock_rawClone(proto)

Registered as the tag's cloneFunc. Deep-copies the message tree so mutating a block's body doesn't leak into the proto, clones the arg names, and carries over scope, isActivatable, and passStops. This is how method() and block() on a user object produce their receiver copies before IoBlock_method fills in the new content.

IoBlock_rawProfilerTime(self)

Direct accessor for accumulated clock() ticks spent in this block. Matched setter is IoBlock_rawResetProfilerTime.

IoBlock_rawResetProfilerTime(self)

Zeros the profiler accumulator. Exposed as a raw helper so profiler drivers (scheduler/debug tooling) can reset without synthesizing a message send.