loom/doc/lib-ref.md

51 KiB

This is the reference manual for all Loom objects and methods (i.e. the "library"). It is not the language reference, but since Loom is mostly library, this holds the bulk of the documentation.

It is generated via (extremely hacky) script from the Loom sources and comments therein.

Loom Class Heirarchy

Well-known Objects

class AbstractDict < Object

Abstract base class for dictionaries.

Subclasses will need to define size, at and each_value_and_key.

Enumerable is a delegate, so each and friends work. Keys take the role of index in this case.

Inner methods

  • _copy |deep|

    (internal, undocumented)

  • == |other|

    Dictionaries are equal if both are subinstances of AbstractDict and corresponding key and value pairs are equal according to ==.

  • at (abstract)

  • copy

    Return a copy of self of the same class with the same keys and values (but not Pairs).

  • deepCopy

    Return a copy of self of the same class with deep copies of the keys and values.

  • each_value_and_key (abstract)

  • fetchOr (abstract)

  • has_key (abstract)

  • keys

    Return a Vector containing all of the keys.

  • size (abstract)

  • str

    Produce a human-friendly printable string

  • values

    Return a Vector containing all of the values.

class AddonTrait < Trait

AddonTraits are bundles of methods that can be added to new classes. They are basically mix-ins.

An AddonTrait can contain methods just like a class but cannot be instantiated. Instead, it must be added to a class as an inner delegate. Methods do not have access to the class's slots. Instead, they must send messages to self.

Outer methods

  • new |*delegates|

    Create a new AddonTrait; zero or more arguments are delegates.

Inner methods

  • new

    Fails; instances cannot be instantiated.

  • subclass |slots, *delegates|

    Convenience method; common interface with Class. Equivalent to AddonTrait.new(self).

class Block < Method

Blocks are unnamed functions defined inside method or block invocations (i.e. Lambdas). While it is possible to create a Block (by way of creating an intermediate ProtoMethod first), you will usually want to just use the { ... } syntax instead.

See the language reference for more details.

Block cannot be subclassed.

Outer methods

  • new

    Fails with an error; should not be called.

Inner methods

  • assert |*msgparts|

    Evaluate self and fail with a message if it returns false. Message is the arguments joined with a space separator.

  • assertmsg |*msgparts|

    Beginnings of a test framework. Like Block::assert but always prints the message and prints FAILED! on failure.

  • benchmark |action|

  • call |*args|

    Invoke this Block with arguments and return the result.

  • callAndEnsure |ensure_block|

    Evaluate self, then ensure_block. Returns the result of self if it is allowed to complete (i.e. doesn't exit via exception or return). ensure_block is guaranteed to always run, regardless of how self is exited.

  • catch |exception_class, handler_block|

    Evaluate self and return its result.

    If doing so causes an exception to be thrown (with Context::throw) and the object's class is exception_class or one of its subclasses, evaluates handler_block (which must be a Block) with the exception object as its parameter and returns the result of that block instead.

  • catchAndEnsure |klass, handler, ensure_block|

    Like catch except that the ensure_block will always be evaluated. Specifically, it:

    1. Evaluates self. If no exception is thrown, the result is returned, as with call().

    2. If an exception was raised that is an instance of klass, it then evaluates handler with the exception as its argument and (if there isn't another exception) returns its result.

    3. Evaluates ensure_block with no arguments and discards the result. This will always happen, regardless of how the the blocks exited.

  • copy

    Blocks aren't copyable so this returns self

  • deepCopy

    Blocks aren't copyable so this returns self

  • str

    Return a human-friendly String describing self.

  • while |body|

    Repeatedly evaluates self, which must return true or false. Each time it returns true, it then evaluates the body, also a block.

    Returns the result of the last call to body or nil if it was never called.

  • whileFalse

    Evaluates self until it returns True instead of False.

  • whileTrue

    Evaluates self until it returns False instead of True. Any other result is an error.

    Equivalent to Block::while called with an empty block argument.

class Boolean < Object

Class of the two Boolean values (True and False, also spelled true and false).

Most methods are actually implemented as outer methods by each of the instances in order to provide behaviour specific to their truth value.

For example, the method if (evaluate block if true) has an implementation in both True and False; True's implementation always evaluates the block and False's never does. An expression like

  a > b .if { do_thing(a,b) }

does the expected thing because the conditional's response contains the expected if implementation.

Is is not possible to instantiate or subclass Boolean.

Inner methods

  • && |body|

    Short-circuited boolean and.

    If self === True, evaluates block body and returns its result; otherwise, returns self.

  • || |body|

    Short-circuited boolean or.

    If self === False, evaluates block body and returns its result; otherwise, returns self.

  • clone

    Booleans are unique and so can't be cloned; just returns self.

  • ifElse |true_body, false_body|

    Evaluate true_body if self === True; false_body otherwise. Returns the result of the evaluated block.

  • ifNot |body|

    Evaluate body if self === False.

  • str

class Class < Trait

The metaclass; all classes are instances of class Class. This includes Class itself.

Class provides the outer interface for basic class behaviour, specifically instance creation (i.e. factory methods) subclass creation, and the ability to access the new class's inner method dictionary.

Inner methods

  • <= |klass|

    Test if RHS is self or a subclass of it.

  • < |klass|

    Test if RHS is a subclass of self

  • >= |klass|

    Test if RHS is self or one of its superclasses.

  • > |klass|

    Test if RHS is a superclass of self.

  • abstract_method |name|

    Define a method with the given name. Calling it will throw a fatal error.

  • abstract_subclass |*args|

    Define an abstract subclass. Just like subclass except that initialize will throw a fatal error.

  • accessible |slotname|

    Equivalent to calling both 'readable' and 'writeable'.

  • new |*args|

    Create a new instance of self and call its initialize method with all of the arguments new received.

  • readable |slotname|

    Add a getter to self whose name is given by slotname that retrieves the contents of the slot named by slotname.

  • slots

    Return a Vector containing the names of all of the slots an instance of self will have in a well-defined order. This includes the slots of all of the superclasses in their order before this class's slots.

  • str

    Return a human-friendly printable description of self. This is the annotation if set; otherwise, it will make something up.

  • subclass |slots, *delegates|

    Create and return a subclass of self. slots is a (possibly empty) vector of symbols that represent the names of the slots instances will have. If one or more delegates is given, they are added to the new class's list of inner delegates. Delegates must be AddonTraits.

    subclass will create the new class's slots method.

  • superclass

    Return the superclass of self. This is always the first inner delegate. Returns null if there is none.

  • writable |slotname|

    Add a setter to self that sets the contents of the slot named by slotname to its argument and returns the new value. The method is named by slotname but has an underscore ("_") appended so that the field assigment syntax will work.

addon Comparable

Can be added to classes whose instances have a well-defined order to provide comparison with respect to that order. The delegating class must implement method < (i.e. less-than) as well as provide a reasonable implementation of ==.

Inner methods

  • <= |other|

    Test if self is less than or equal to other.

  • < |other|

    Fails if called; this should be implemented by the class.

  • >= |other|

    Test if self is greater than or equal to other.

  • > |other|

    Test if self is greater than other.

class Context < Object

Context objects represent the local activation record (i.e. "stack frame") of the current method or block. The hold local variables and provide the interface for accessing variables.

Instances are created by the interpreter. It is not possible to create or copy a Context from Loom code or to create a subclass of Context.

Inner methods

  • copy

    Contexts aren't copyable so this returns self.

  • deepCopy

    Contexts aren't copyable so this returns self.

  • defglobal |name, value, *maybe_annotation|

    Defines a global variable or constant.

    self.defglobal(name, value [, annotation])

    'name' must be a symbol and must not be defined in the global namespace. 'value' can be any value and will be assigned to it. If a third argument is given, it is expected to be the annotation. (More than 3 arguments are an error.)

    Providing an annotation is equivalent to doing value.annotation = annotation; depending on what value is, this may be a no-op. The primary use for this is making it easy to tell classes their names.

  • ensure |ensure_block|

    Attach a Block to here that will be evaluated after this method call terminates, regardless of how that happens. The block's result is discarded.

  • fail

    Exit with a fatal error. Should be overridden in the syslib to throw a Failure exception.

  • get |name|

    Given a symbol name, return the value of the variable named by that symbol. Fails if the name is undefined.

    Roughly equivalent to a bare variable. That is,

      foo
    

    and

      Here.get(:foo)
    

    do the same thing, with the former having the advantage of compile-time checking.

  • getglobal |name|

    Given a symbol name, return the value of the global variable named by that symbol. Fails if the name is undefined.

    Unlike get or ordinary name lookup, this jumps directly to the global namespace, bypassing any local or instance variables that may have masked it.

  • global_scope

    Return the global scope associated with self; this could be self if self is the global context.

  • has |name|

    Test if there is a variable visible in the current scope (this one OR an outer scope) with the given name. Returns true if there is, false otherwise.

  • hasglobal |name|

    Test if there is a global variable with the given name. Returns true if there is, false otherwise.

  • method_scope

    Return the innermost context that is not a block's context. Specifically, if self belongs to a block evaluation, it searches outward until it finds the first context that does not. This will either be a method's or the global context. Otherwise, it returns self.

  • names

    Return a Vector containing all of the names defined locally in this context. (I.e. it does not include visible names defined in outer scopes.)

  • outer

    Return the next outer scope or nil if this is the global context.

  • return |result|

    Causes the context to return. That is, the function stops being evaluated and the result is given to the caller.

    If self is the global context, this will fail.

  • set |name, value|

    Given a symbol name and value, store the value at the variable named by the name according to the standard scope resolution rules. Fails if the name is undefined or unwritable.

  • str

  • super_send |message, *args|

    Equivalent to super_sendv (i.e. sends message with the search starting in the calling method's owner's delegates) but takes a variadic argument list.

  • super_sendv |message, args|

    Send message message to self with args as the list of parameters, but start the method search at the delegate list of the object which owns the method that's doing the send.

    This lets us invoke a superclass's method that has been overridden in the current class.

  • throw |obj|

    Throw an exception. obj may be any object that is an instance of Object or one of its subclasses; 'catch' statements will catch this if the the thrown object is an instance or subinstance of the class it's waiting for.

addon Enumerable

This is an addon which provides methods for applying a block to every element in a sufficiently vector-like object.

Classes delegating to Enumerable must implement size, and at as expected. Classes that do not behave like a zero-based array must also implement each_value_and_key.

Inner methods

  • contains |value|

    Test if an element equal to value is present.

  • each |block|

    Call 'block' on each element in increasing order.

  • each_idx |block|

    Convenient wrapper around each_value_and_key.

  • each_value_and_key |block|

    Call 'block' on each element in increasing order with the element and its index as arguments.

    This will work for any collection whose keys are a continuous range of integers between 0 and one less than the number of items (i.e. like a Vector). Collection classes that do not follow this protocol need to provide their own each_value_and_key which must evaluate the block for each key and corresponding value in the collection exactly once.

    (Warning: future directions may add additional constraints on this including ordering.)

  • has_all |block|

    Test if block returns true for all items in self

  • has_any |block|

    Call 'block' on some or all elements in self and return true if block returns true for at least one element.

  • has_none |block|

    Test if block returns false for all items in self

  • inject |initial, block|

    Combines all elements of self by applying a two-argument block where the second argument is the current element and the first the result of the previous block or 'initial' if it is the first call.

  • map |block|

    Call 'block' on each element in increasing order and return a vector containing the results of each block call.

  • reduce |block|

    Combines all but the first elements of self by applying a two-argument block where the first argument is the result of the previous block evaluation and the second is the current item. The first element is used as the initial value.

    This is like inject except that the first element is used as the initial value.

  • reject |block|

    Like 'select' but returns only those items for which the block returns false.

  • select |block|

    Classic reduce. Return a Vector of those items for which the block returns true.

class Exception < Object

Base class for all Exceptions. Exception objects should be subinstances of this class unless there's a very good reason not to.

Inner methods

  • initialize |txt|

  • str

  • text

    Base class for all Exceptions. Exception objects should be subinstances of this class unless there's a very good reason not to.

class Failure < Exception

Concrete base class for exceptions originating in software errors. Throwing one of these indicates that the program's state is invalid; these should only be caught as part of exiting gracefully.

object False = Boolean.new

The False boolean value. (Also spelled false).

Outer methods

  • & |other|

    Perform a boolean and operation; return True if self and other are both True and False otherwise. Both self and other must be booleans.

  • | |other|

    Perform a boolean or operation; return True if self and/or other is True and False if it isn't. Both self and other must be booleans.

  • if |body|

    Evaluate body if self === True and don't if self === False.

    Returns the body's value if it's evaluated.

  • not

    Return the logical inverse of self.

class File < Object

Basic file access objects. Handles reading and writing of strings. Binary data is also read into or written from strings; sorry about that.

Outer methods

  • on |path, mode_str, block|

    Opens a file according to path and mode_str (see File::initialize), then evaluates block with the File instance as its argument, closes the handle, and returns the block's result. It is safe to exit the block via return or an exception; the handle will still be closed.

Inner methods

  • _check |write_mode|

    (internal, undocumented)

  • close

    Close this file handle.

  • copy

    File objects are not copyable so this returns self.

  • eof

    Test if the file handle is open for reading and at end-of-file

  • initialize |path, mode_str|

    Opens this File onto the file at path. mode_str is expected to be a C-style open mode string (one of "r" or "w" with an optional "b" appended.)

  • is_ok

    Test if self is not in an error state. Note that end-of-file is not considered an error.

  • is_open

    Test if self is open.

  • readbytes |count|

    Read 'count' bytes from the stream and return them in a string. If count exceeds the remaining bytes in the file, return what's left. If already at EOF, returns an empty string.

  • readline

    Read a newline-delimited line and return it, minus the newline character. If EOF is reached before the next delimiter, all characters are returned. If already at EOF, returns an empty string.

  • str

    Return a printable description.

  • writebytes |bytes|

    Write a string to the file unmodified.

  • writeline |line|

    Write a string to the file and append a newline.

class IntFH < Object

Internal file handle. This provides code and data used for interfacing with the underlying IO routines (currently C++ std::iostream, but no promises).

This is an internal implementation detail of class File. You should never need to touch one of these.

object Lobby = Object.new

The object in which all toplevel expressions are evaluated.

A toplevel expression is a Loom expression that has been read from a Loom source file or entered via the REPL. It is wrapped in a method which is then invoked. This method is an outer method of Lobby.

Lobby is an instance of Object but has several slots:

  • Argv holds the command-line arguments the interpreter was invoked with.
  • LobbyFlag is True and deprecated.
  • _last holds the last expression evaluated on the REPL.

There are also several methods.

Outer methods

  • _check_tl |expr|

    (internal, undocumented)

  • _eval_toplevel_expr

    Given a Loom expression, evaluate it in the toplevel context. (This is not quite consistent with the rest of the system.)

    It is aliased to eval_toplevel_expr, which is called by the REPL and file load interface.

  • _eval_toplevel_expr_with_name_checks |expr|

    (internal, undocumented)

  • _time_now

    Return the time in microseconds since some point in the past. This is here for benchmarking only.

  • config |var, yes|

    System configuration settings:

    full_namecheck - Do a thorough check for undeclared names. If false, skips some of the slower cases.

    namecheck_fatal - Treat missing names in nested blocks as fatal errors. If false, they're warnings.

    optimize - Optimize method definitions. Experimental; off by default.

  • import |path|

    Read in source code in the file at path and evaluate it within the context of the lobby.

  • stack_max

    Return the maximum call depth.

  • stack_max_ |max_depth|

    Set the maximum call depth. This is helpful in exiting gracefully when your code contains an infinite recursion.

    max_depth must be a positive integer. Setting it too low is a very bad idea.

  • str

class Method < Object

Contains the executable code of Loom object method in whatever format the interpreter prefers. Primitive methods (i.e. part of the interpreter) are also instances of Method.

There is not much you can do with this class by itself; it's all done in existing libraries or syntax expansion.

Instances are normally created via ProtoMethod.make_method; creating one with new may or may not work and probably won't be useful.

Method cannot be subclassed.

Outer methods

  • new |arg_names, restvar, locals, body|

    Create an instance of Method.

    Don't use this. It's only here to help the older tests.

Inner methods

  • copy

    Methods aren't copyable so this returns self

  • deepCopy

    Methods aren't copyable so this returns self

  • str

class MsgExpr < Object

Instances represent Loom message-send expressions inside the Loom interpreter. Each contains three values: the receiver, the message and the argument list.

  • receiver is the Loom expression whose value will receive the message.

  • message is a Symbol representing the nameof the message to send.

  • args is a (possibly empty) Vector of objects; their results once evaluated will be the arguments included with the message.

MsgExpr is an ordinary slotted class.

Outer methods

  • slots

Inner methods

  • _fold_vector_dot_with

    (internal, undocumented)

  • _is_protomethod_new

    (internal, undocumented)

  • _is_rudimentarily_foldable |fold_msg|

    (internal, undocumented)

  • _is_safe_to_eval |fold_msg|

    (internal, undocumented)

  • _is_simple_arithmetic

    (internal, undocumented)

  • _is_vector_dot_with

    (internal, undocumented)

  • _most_folded_backend |fold_msg|

    (internal, undocumented)

  • == |other|

    MsgExpr objects are equal if the receiver, message and argument lists are also equal. This doesn't necessarily mean that their evaluated results will be equal, but that's Turing Completeness for ya.

  • args

  • deepCopy

    Create a copy of self with deep copies of receiver and argument list

  • each_leaf |block|

    Traverse self and all referenced MsgExpr objects and for each leaf node (i.e. receiver or parameter that is not a MsgExpr), call block with it as argument.

    Each block gets called with the leaf and the outer MsgExpr as arguments.

  • initialize |receiver, message, args|

    Initializer.

  • is_foldable

    Can this MsgExpr be (partially) folded?

    A MsgExpr is foldable if its receiver and args are foldable OR it is safe to invoke here and now and replace with the result.

  • is_trivial_eval

    Is this object trivial to interpret? (I.e. does the interpeter simply evaluate it to itself?)

  • message

  • most_folded

    Return self as folded as possible. (See Object::most_folded for details.)

  • most_folded_unsafe

    most_folded, but it must not be possible to modify the result. The only extra case we handle here is Vector.with(...), but that's important.

  • receiver

  • str

object Nil = NilClass.new

The null object. (Also spelled nil).

Outer methods

  • is_nil

    Return true if self is nil.

class NilClass < Object

This is the class of the Nil (aka nil) object.

It can neither be instantiated or subclassed. nil is the only instance.

class Number < Object, Comparable

This is the class for integer and float-point numbers. It supports common arithmetic operators plus some extras.

When performing arithmetic between integer and floating-point values, the integer will be promoted to float beforehand and the result will be a float. However, operations between integers will yield integers.

It is not possible to create a subclass of Number.

Note: the underlying implementation is somewhat simpleminded and does everything in C++, so there's a chance that future releases will be different enough to break code that depends on the fine details of this implementation. Sorry; I'll try not to do that.

Inner methods

  • % |other|

    Modulo

    Both arguments must be integers

  • & |other|

    Bitwise AND

    Both arguments must be integers

  • * |other|

    Multiplication (aliased to mult)

  • + |other|

    Addition (aliased to add)

  • - |other|

    Subtraction (aliased to sub)

  • / |other|

    Division (aliased to div)

  • < |other|

    Test if self is less than the argument. Integers and floats are considered equivalent for this purpose. Argument must be a number.

  • << |other|

    Left shift

    Both arguments must be integers

  • == |other|

    Test for numeric equality.

    If both arguments are integers, it compares them as integers. Otherwise, both values are compared as floating point values and subject to the limitations therein.

    Numbers are never equal to non-numbers.

  • >> |other|

    Right shift

    Both arguments must be integers

  • ^ |other|

    Bitwise exclusive-OR

    Both arguments must be integers

  • -> |to|

    Construct a Range with 'from' and 'to' values from self and to.

  • abs

    Return the absolute value of self.

  • between |lower, upper|

    Test if self is inclusively between upper and lower.

  • hex

    Return as a string 0x-prefixed hex number

  • is_float

    Test if the underlying number is a floating-point value. Note that 2.0 is still a float while 2.0.truncate is not.

  • is_int

    Return true if self is an integer; false if it's a float. Note that an integer is different from a float with no fractional part.

    That is, 2 is an integer but 2.0 is not; 2.0.truncate is one, however.

  • max |other|

    Return the larger of self and other.

  • min |other|

    return the smaller of self and other.

  • pack

    Return an 8-byte String containing the bytes of self in network (i.e. big-endian) order. self must be an integer; it is an error to pack a floating-point value.

  • truncate

    Compute the nearest integer not greater in magnitude than self.

  • | |other|

    Bitwise OR

    Both arguments must be integers

class Object

Base class for all classes.

It can be instantiated and this is useful for creating objects with only outer methods.

Inner methods

  • === |other|

    Test if self and other are the same actual object in memory. Should not be overridden by subclasses.

    Note: the only reason you should ever use this is to implement ==.

  • _does_not_understand |message, *args|

    Fails with an error message.

    This message gets sent to an object if a method lookup fails. message is the name of the missing method and is followed by the remaining argument list.

    Subclasses may override this to different things.

  • _print

    Debug print method. No guarantees for the future.

  • _str_layout

    Debug print method. No guarantees for the future. Uses the layout-level printer.

  • != |other|

    Inequality. I.e., test if self == other is false.

  • == |other|

    Test if self is equal to other, where equality is defined by the class itself. Subclasses should override this as necessary; by default, it's equivalent to ===.

  • => |value|

    Construct a Pair with the LHS as key and the RHS as value.

  • add_delegate |delegate|

    Add a new AddonTrait to the list of outer delegates.

  • add_method |name, method|

    Add Method method to self's (outer) method dictionary with name name (a Symbol). method must have been defined with a list of slots that exactly matches the this object's list of slots or undefined behaviour may occur.

  • add_slot |name, initial_value|

    Add a slot named by name to the end of this object's list of slots and set its initial value to initial_value. (This is an "outer" slot; inner lots aren't a thing.)

    It is an error if there is already a slot with that name or if this is not a slotted object.

  • alias_method |from, to|

    Create a new (outer) method dictionary entry named to that references the method named by from. Both methods must belong to self and not a delegate. from and to are symbols.

  • annotation

    Retrieve self's annotation string if self's layout supports that. Otherwise, returns an empty string.

  • annotation_

    Set self's annotation string if self's layout supports that. Otherwise, does nothing. The argument must be a string.

  • class

    Return self's class (i.e. the first outer delegate). Returns nil if there isn't one.

  • clone

    Create and return a shallow copy of this object. Not all objects can be cloned and unique objects (e.g. nil) will just return themselves.

    In general, you should use copy or deepCopy instead of this. clone is allowed to have implementation-specific quirks while the other two are not.

  • copy

    Create a shallow copy of this object, whatever that means for this class.

    copy is mostly the same as clone but the latter is more implementation-dependent and has wierd corner cases. copy should (in theory) be more consistent.

    Note that for objects that cannot or should not be copied, copy will simply return the object.

  • deepCopy

    Create a deep copy of this object as determined by the class.

    A deep copy is a copy in which (notionally) all of the objects it references are also copied.

    WARNING: we currently do not correctly handle multiple references to the same object; each will be replaced with a different copy. In the case of circular references, an infinite loop is possible.

    Defaults to shallow copying; subclasses should do the right thing.

    Note that for objects that cannot or should not be copied, deepCopy will simply return the object.

  • delegates

    Return the list of delegates in a Vector

  • get_method |name|

    Retrieve the Method object associated with symbol name in selfs method dictionary. Fails if not present.

  • has_method |name|

    Return true if self contains a method named by method. Returns false if not, even when a delegate has it.

  • id

    Return a unique ID identifying this specific object.

  • initialize |*args|

    Default initializer; a stub that does nothing so that new has something to call.

  • is_a |klass|

    Test if self is an instance of klass or one of its subclasses.

  • is_foldable

    Can this object be reduced to something smaller? That is, if it's not fully foldable, can at least some of its subexpressions be fully folded?

    Returns false if self is already trivially evaluable OR if it cannot be safely folded any further.

    (See Object::most_folded for a longer explanation.)

  • is_nil

    Return true if self is nil.

  • is_trivial_eval

    Is this object trivial to interpret? (I.e. does the interpeter simply evaluate it to itself?)

  • most_folded

    Return a value (not necessarily a copy!) that is equal to this object but as folded as possible.

    "Folding" here is a reference to the concept of "constant folding"; that is, evaluating expressions at compile time when it is safe to do so.

    Folding an Object attempts to return the value that you would get if the interpreter evaluated it. This is often not possible (e.g. if it contains a reference to a variable or some other non-constant state or if evaluation has side effects). In this case, some of its subexpresssions may or may not be folded. We tend to err on the side of caution and only fold things if we know it won't change the meaning of evaluation.

    Most Loom objects simply evaluate to themselves. Exceptions include Quote and MsgExpr; these may or may not fold to something simpler.

    This is the beginning of the Loom optimizer; ProtoMethod::simplified attempts to fold its body expressions. However, this also gets used to detect the use of undeclared variables in Blocks. simplified will expand {...} expressions into the intermediate ProtoMethod object, which is then queried about its variable use.

  • most_folded_unsafe

    Like most_folded, but the caller must guarantee that the returned object is never modified.

  • outer_slots

    Return a Vector containing the names of self's actual slots in order.

  • print

    Print this object on the output stream. Equivalent to self.str.print.

  • println

    Print this object on the output stream followed by a newline.

  • send |message, *args|

    Sends the given message (a Symbol) to self with the remaining arguments as the message's argument list.

  • sendv |message, args|

    Like send, but takes the arguments as a single array.

  • str

    Return a human-friendly String describing self.

class Opaque < Object

An Opaque object represents a value managed by non-Loom libraries, either from the interpreter or via an FFI.

For example, the File class internals use an Opaque to hold the pointers to C++ filestreams. These are only visible to the primitive methods that interface with the C++ IO library.

You cannot do anything useful with an Opaque from inside Loom beyond passing it around, and then only in ways that the underlying primitives can use.

Inner methods

  • copy

    Fails with an error.

    Unlike most uncopyables whose copy and deepCopy just return self, we assume that any attempt to copy one of these is an error in the class that owns it.

  • deepCopy

    Fails with an error.

    Unlike most uncopyables whose copy and deepCopy just return self, we assume that any attempt to copy one of these is an error in the class that owns it.

class Pair < Object

Pairs represent an entry in a dictionary. They contain key and value.

Inner methods

  • == |other|

    Pairs are equal iff their corresponding keys and values are equal.

  • copy

    Returns a new Pair with the same key and value

  • deepCopy

    Returns a new Pair with deep copies of the key and value

  • initialize |newKey, newValue|

  • key

  • str

  • value

  • value_ |val|

class ProtoMethod < Object

Precursor data structure to hold the contents of a Method or Block before defining it. This is an ordinary slotted class with five fields:

  • args - Vector of symbols; list of formal arguments.
  • restvar - nil or the name of the variadic argument
  • locals - Vector of symbol; list of non-argument local variables.
  • body - Vector of Loom expressions; the method body.
  • annotation - nil or a descriptive String, typically used for diagnostics.

Instances are usually created using the brace syntax but new works as expected and is useful for metaprogramming.

Outer methods

  • _getter |slotname|

    (internal, undocumented)

  • _insta_fail |klass, text|

    (internal, undocumented)

  • _setter |slotname|

    (internal, undocumented)

  • slots

Inner methods

  • _check_local_lexicals

    (internal, undocumented)

  • _check_names |known_names, node|

    (internal, undocumented)

  • _make_method_no_opt |outernames|

    (internal, undocumented)

  • _make_method_opt |outernames|

    (internal, undocumented)

  • _validate_names |name_dict|

    (internal, undocumented)

  • _warn_missing_name |name|

    (internal, undocumented)

  • _warning_advisory |msg|

    (internal, undocumented)

  • _warning_fatal |msg|

    (internal, undocumented)

  • == |other|

    Equality test. ProtoMethod objects are equal if and only if all of the fields are also equal according to ==.

  • annotation

    Retrieve a copy of the annotation string (or nil, if unset)

  • args

    Retrieve a copy of the formal argument list

  • body

    Retrieve a deep copy of the body.

  • copy

    Returns a copy of self.

    Equivalent to deepCopy because all ProtoMethod copies are deep.

  • deepCopy

    Create a copy of self with deep copies of all fields.

  • initialize |argument_list, rest_symbol, local_list, body, annotation|

    ProtoMethod initializer.

    Args:

    • argument_list - vector of symbols; list of args
    • rest_symbol - nil or a symbol; name of the variadic arg if given
    • local_list - vector of symbos; list of local args
    • body - vector of quoted evaluatable items
    • annotation - nil or a string
  • locals

    Retrieve a copy of the list of local variables

  • make_block |outer_here|

    Create and return a block based on self. Argument must be the context (i.e. Here) in which it is defined. If it is not, the behaviour is undefined.

    (Internal; do not rely on this.)

  • make_method |slots|

    Create and return a method based on self. slots must be a list of symbols containing the owning object's slots in the SAME ORDER as the owner's. If they do not match, behaviour is undefined.

  • restvar

  • simplified

    Return a copy of self that has been simplfied via simplify_in_place.

  • simplify_in_place

    Simplify (aka optimize) this ProtoMethod, in place (i.e. this object, not a copy of this object). Currently, 'simplify' means to attempt to fold (via most_folded) every expression or subexpression in this object's body and to recursively simplify any ProtoMethods found.

    This takes advantage of the fact that MsgExpr::most_folded will evaluate the ProtoMethod.new expression created by the {...} block syntax.

    Note: most of the time, you should use ProtoMethod::simplified instead.

  • str

    Return a printable representation of self.

  • unknown_names |extra_names|

    Return the list of names referenced by the body that are not locally defined (i.e. names that need to be present in an outer scope) and not listed in the argument, which is a vector of symbols.

    (Internal; do not rely on this.)

  • validate_as_method |slots|

    Search self for references to undeclared names. slots is an array of symbols containing names that were declared elsewhere and so will be resolvable at runtime; this is almost always the list of slots declared by the class that will own this method.

    If a missing name is called, ProtoMethod::_warning is invoked with an error message; depending on settings, this may be a fatal error or a warning.

    This can also be used to check Blocks, since they will also have Self defined in their scopes.

class Quote < Object

A Quote is simply an object that holds a reference to one other object. Its primary purpose is to delay evaluation in a method body.

It is mostly equivalent to a slotted object with a single slot. However, the Loom interpreter (or equivalent) will evaluate a Quote instance by retrieving the wrapped value. This allows us to (e.g.) specify a symbol in a way that yields the Symbol object itself rather than looking it up as a variable.

Outer methods

  • new |value|

    Create a new instance holding value.

Inner methods

  • == |other|

    Quotes are equal if their values are equal

  • deepCopy

    Copy self the wrapped object.

  • is_foldable

    Can this object be reduced to something smaller? That is, if it's not fully foldable, can at least some of its subexpressions be fully folded?

    Returns false if self is already trivially evaluable OR if it cannot be safely folded any further.

    (See Object::most_folded for a longer explanation.)

  • is_trivial_eval

    Is this object trivial to interpret? (I.e. does the interpeter simply evaluate it to itself?)

  • most_folded

    Return self.value if self can be safely folded; otherwise, just return self.

  • str

  • value

    Return the value self is holding.

class Range < Object

Simulates a vector of integers sufficiently well to enumerate over. This lets you do boring loops with integer counters via Enumerable.

Normally, you will want to use Number::-> to create instances:

  1 -> 10 .each{|n| "n = " + (n.str) .println };

or, to increment by a different amount:

  1 -> 10 * 2 .each{|n| "n = " + (n.str) .println };

Inner methods

  • * |new_by|

    Return a new range with the same from and to values as self but with a new by (i.e. increment) value.

  • as_vector

    Convert to a Vector.

  • at |index|

    Array-style reader.

  • by

  • from

  • initialize |f, t, b|

    Initializer. f and t are the first and last values in the range and 'b' is the increment.

  • size

    Array-style size

  • str

  • to

class RuntimeError < Exception

Base class for exceptions meant to be caught as part of normal operation. (I.e. throwing one of these doesn't necessarily mean the program can't keep going.)

class SlowDict < AbstractDict

SlowDict - A basic O(n) dictionary.

Inner methods

  • _index_of |key|

    (internal, undocumented)

  • at |key|

    Return the value associated with key. Fails if not present.

  • atPut |key, value|

    Store value in self at key.

  • each_value_and_key |block|

    Evaluate block each item and corresponding key in self. Parameters are |value, key|.

  • fetchOr |key, missing_action|

    Retrieve the value at key. If there is none, evaluate block missing_action with the key as its argument and return its result instead.

  • has_key |key|

    Test if key is present.

  • initialize

  • size

    Return number of items

class String < Object, Enumerable, Comparable

Fundamental built-in string type. Behaves like a Vector of single-character String objects.

Cannot be subclassed.

Note: Currently, Loom only supports 8-bit characters (I.e. ASCII or possibly your preferred 8-bit extension). This is considered a shortcoming that should be fixed, but it is unclear what that will mean when accessing individual characters in a String. Will String be an array of bytes or an array of encoded characters?

Outer methods

  • concat |*strings|

    Return a new String consisting of all of the arguments appended together. All of the arguments must also be strings.

  • digit

    Lowest and highest encode value of various ranges of characters. (Assumes you're using an encoding where these are contiguous.)

  • lower

    Lowest and highest encode value of various ranges of characters. (Assumes you're using an encoding where these are contiguous.)

  • new |size|

    Create a new String of length size bytes. All characters are null. size must not be negative.

  • upper

    Lowest and highest encode value of various ranges of characters. (Assumes you're using an encoding where these are contiguous.)

Inner methods

  • + |other|

    Return a new string containing self and other appended together.

  • < |other|

    Test if self is lexically less than other according to the underlying string comparison routine. This is currently the C++ < string operator, but this may change.

  • == |other|

    Test if self and other are equal. Returns true if other is also a String, has the same length as self and the same values at all corresponding indexes.

  • _ctype_test |range|

    (internal, undocumented)

  • at |index|

    Return the character at index as a separate, 1-character-long string. index must be between 0 and self.size - 1.

  • atPut |index, value|

    Set the character in self at index to value, which must be a string with a length of 1. index must be between 0 and self.size - 1.

  • intern

    Return a Symbol whose name is the contents of self.

  • is_alnum

    Test the first character of self for the given condition. Returns false if self is empty.

  • is_alpha

    Test the first character of self for the given condition. Returns false if self is empty.

  • is_digit

    Test the first character of self for the given condition. Returns false if self is empty.

  • is_lowercase

    Test the first character of self for the given condition. Returns false if self is empty.

  • is_uppercase

    Test the first character of self for the given condition. Returns false if self is empty.

  • print

    Write self to standard output.

    (Note that due to the development process, this is currently independent of the File class; it works by using the underlying C++ IO routines directly.)

  • resize |new_size|

    Change the size of self to new_size. If larger, the new characters are initialized 0. new_size must not be negative.

  • size

    Return the length of self.

  • str

    Returns a human-friendly description of self. In this case, it's a copy in which all non-printable characters have been replaced by \xXX codes.

  • to_number

    Given a string, parse it as one of the supported numeric types. It should really handle all of the numeric literal formats the parser does, but it doesn't. Maybe in the future?

  • unpack

    Given a string, treat the first 8 bytes as an integer in network-order and return it as a Number. If there are fewer than 8 bytes, the missing bytes are presumed to be zero and on the most significant part of the number.

    It is an error if Number cannot hold this value for some reason.

class Symbol < Object

Symbols are objects representing names. They are used by Loom itself to represent names in Loom code.

There is exactly one instance of each Loom symbol. Thus, for all Symbols, if s == s is true, then s === s is also true.

It is not possible to create a subclass of MsgExpr.

Inner methods

  • is_foldable

    Can this object be reduced to something smaller? That is, if it's not fully foldable, can at least some of its subexpressions be fully folded?

    Returns false if self is already trivially evaluable OR if it cannot be safely folded any further.

    (See Object::most_folded for a longer explanation.)

  • is_trivial_eval

    Is this object trivial to interpret? (I.e. does the interpeter simply evaluate it to itself?)

  • str

  • unintern

    Return a String containing the same text as self.

class Trait < Object

Abstract base class for all objects that have an inner method method dictionary. Provides methods for managing inner methods.

It can neither be instantiated or subclassed.

Inner methods

  • copy

    Trait and derived classes are not copyable, so this returns self.

    (Well, they can be via clone, but it's much more valuable for them to be uncopyable and to prefer delegation.)

  • deepCopy

    Trait and derived classes are not copyable, so this returns self.

    (Well, they can be via clone, but it's much more valuable for them to be uncopyable and to prefer delegation.)

  • inner_add_delegate |delegate|

    Add a new AddonTrait to the list of inner delegates.

  • inner_add_method |name, method|

    Add Method method to self's inner method dictionary with name name (a Symbol). method must have been defined with a list of slots that exactly matches this trait's instances' list of slots or undefined behaviour may occur.

  • inner_alias_method |from, to|

    Create a new inner method dictionary entry named to that references the method named by from. Both methods must belong to self and not a delegate. from and to are symbols.

  • inner_delegates

    Return the list of inner delegates.

  • inner_get_method |name|

    Retrieve the Method object associated with symbol name in selfs inner method dictionary. Fails if not present.

  • inner_has_method |name|

    Return true if self contains an inner method named by method. Returns false if not, even when a delegate has it.

object True = Boolean.new

The True boolean value. (Also spelled true).

Outer methods

  • & |other|

    Perform a boolean and operation; return True if self and other are both True and False otherwise. Both self and other must be booleans.

  • | |other|

    Perform a boolean or operation; return True if self and/or other is True and False if it isn't. Both self and other must be booleans.

  • if |body|

    Evaluate body if self === True and don't if self === False.

    Returns the body's value if it's evaluated.

  • not

    Return the logical inverse of self.

class Vector < Object, Enumerable

Fundamental one-dimensional array type.

Cannot be subclassed.

Note: this implementation leans heavily on the underlying language's libraries. Future directions may split this into something more primitive and a Loom wrapper that puts back the convenient methods.

Outer methods

  • new |size|

    Create a Vector of the specified size, filled with nil. If the size is zero or omitted, the vector is empty.

  • with |*values|

    Create a new vector initialized to the values of the arguments.

Inner methods

  • == |other|

    Equality tests. self and other are equal if and only if they are both vectors of the same length and corresponding elements are also equal according to ==.

  • + |other|

    Return a copy of self with 'other' (an Enumerable) appended.

  • at |index|

    Return the element at the given index. Fails if the index is invalid (<0 or >= self.size).

  • atPut |index, value|

    Set the value at index to value and return value. index must be between 0 and one less than the size of self. Fails if the index is invalid.

  • deepCopy

    Copy self and deeply copy all elements.

  • join |separator|

    Ruby-style join method. Returns a string containing each item in self after a call to str with separator interleaved.

  • pop

    Remove (in place) and return the last item in Self. If empty, return nil.

  • push |value|

    Append value to self in place, returning self.

  • resize |new_size|

    Change the size of self to new_size. If larger, the new slots are initialized to nil. new_size must not be negative.

  • shift

    Remove the first item from self and return it. Returns nil if empty.

  • size

    Return the length of self.

  • str

    Return a human-friendly string describing the contents of self.

  • unshift |value|

    Insert the argument at the beginning of 'self'.