10.8. Primitives

Primitives are Self methods implemented by the virtual machine. The first character of a primitive’s selector is an underscore (‘_’). You cannot define primitives yourself (unless you modify the Virtual Machine), nor can you define slots beginning with an underscore.

10.8.1. Primitive failures

Every primitive call can take an optional argument defining how errors should be handled for this call. To do this, the primitive is extended with an IfFail: argument. For example, _AsObject becomes _AsObjectIfFail:, and _IntAdd: becomes _IntAdd:IfFail:.

> 3 _IntAdd: ’a’ IfFail: [ | :error. :name |
(name, ’ failed with ’, error, ’.’) printLine. 0 ]
_IntAdd: failed with badTypeError.
0        "The primitive returns the result of evaluating the failure block."
>

When a primitive fails, if the primitive call has an IfFail: part, the message value:With: is sent to the IfFail: argument, passing two strings: the name of the primitive and an error string indicating the reason for failure. If the failing primitive call does not have an IfFail: part, the message primitive:FailedWith: is sent to the receiver of the primitive call with the same two strings as arguments.

The result returned by the error handler becomes the result of the primitive operation (0 in our example); execution then continues normally. If you want the program to be aborted, you have to do this explicitly within the error handler, for example by calling the standard error: method defined in the default world.

The following table lists the error string prefixes passed by the VM to indicate the reason of the primitive failure. If the error string consists of more than the prefix it will reveal more details about the error.

Table 10.5 Primitive failures
Prefix Description
primitiveNotDefinedError Primitive not defined.
primitiveFailedError General primitive failure (for example, an argument has an invalid value).
badTypeError The receiver or an argument has the wrong type.
badTypeSealError Proxy’s type seal did not match expected type seal.
divisionByZeroError Division by zero.
overflowError Integer overflow. This can occur in integer arithmetic primitives or in UNIX (when the result is too large to be represented as an integer).
badSignError Integer receiver or argument has wrong sign.
alignmentError Bad word alignment in memory.
badIndexError The vector index (e.g. in _At:) is out of bounds (too large or negative).
badSizeError An invalid size of a vector was specified, e.g. attempting to clone a vector with a negative size (see _Clone:Filler: and _CloneBytes:Filler: below).
reflectTypeError A mirror primitive was applied to the wrong kind of slot, e.g. _MirrorParentGroupAt: to a slot that isn’t a parent slot.
outOfMemoryError A primitive could not complete because its results would not fit in the existing space.
stackOverflowError The stack overflowed during execution of the primitive or program.
slotNameError Illegal slot name.
argumentCountError Wrong number of arguments.
unassignableSlotError This slot is not assignable.
lonelyAssignmentSlotError Assignment slot must have a corresponding data slot.
parallelTWAINSError Can not invoke TWAINS primitive (another process is already using it).
noProcessError This process does not exist.
noActivationError This method activation does not exist.
noReceiverError This activation has no receiver.
noParentSlot This activation has no lexical parent.
noSenderSlot This activation has no sender slot.
deadProxyError This proxy is dead and can not be used.
liveProxyError This proxy is live and can not be used to hold a proxy result.
wrongNoOfArgsError Wrong number of arguments was supplied with call of foreign function.
nullPointerError Foreign function returned null pointer.
nullCharError Can not pass byte vector containing null char to foreign function expecting a string.
prematureEndOfInputError Premature end of input during parsing.
noDynamicLinkerError Primitive depends on dynamic linker which is not available in this system.
EPERM, ENOENT, ... These errors are returned by a UNIX primitive if a UNIX system call executed by the primitive fails. The UNIX error codes are defined in /usr/include/sys/errno.h; see this file for details on the roughly 90 different UNIX error codes.

The _ErrorMessage primitive, sent to an error string returned by any primitive, returns a more descriptive version of the error message; this is especially useful for UNIX errors.

10.8.2. Available primitives

A complete list of primitives can be obtained by sending primitiveList to primitives. Documentation for a primitive (such as _Clone), can be obtained using at:, thus:

primitives at: ’_Clone’

A list of primitive names matching a pattern can be obtained thus:

primitives match: ’_Memory*’

Some points to note when browsing primitives:

  • Since strings are special kinds of byte vectors, primitives taking byte vectors as arguments can usually take strings. The exception is that canonical strings cannot be passed to primitives that modify the object.
  • Integer arithmetic primitives take integer receivers and arguments; floating-point arithmetic primitives take floating-point receivers and arguments.
  • All comparison primitives return either true or false. Integer comparison primitives take integer receivers and arguments; floating-point comparison primitives take floating-point receivers and arguments.
  • The receiver of a mirror primitive must be a mirror (unless otherwise noted)