Lunar programs frequently use the same name for two related but conceptually distinct objects, for example a class and its constructor, or an operator and the function it invokes. Since in a given scope a name can only have one value, Lunar uses bundle objects to combine multiple natures into one datum.
A bundle combines up to three different "natures." Each nature is the name of an abstract class whose members are all bundles that have that nature. The slots that store the attributes of all three natures exist in all bundles, but the slots for a nature are only used if the bundle has that nature.
Nature | Purpose | Attributes |
---|---|---|
class | A class defines object structure and type | slots, superclasses, modifiers, disjoint |
function | A function defines behavior | methods, requirements, destructuring |
operator | An operator directs parsing | arity, precedence, macro expanders |
Class nature defines the structure and type of members of that class as well as relationships with superclasses. It also contains the set of classes that are declared to be disjoint with this class.
Function nature bundles together a set of methods that define the behavior of the function. It also includes an optional destructuring method used at compile time.
Operator nature is both for unary/binary/ternary operators, which are invoked with a special algebraic expression syntax with left and right precedence but take ordinary expressions as their operand(s), and for prefix/infix macros, which do their own parsing so they can be invoked with idiosyncratic syntax. Operator nature is only used at compile time.
In addition to slots to store the attributes of all three natures, bundles have a name slot. This is useful for interactive debugging, and allows a reference to a bundle from separately compiled code to be linked to the corresponding bundle when that code is loaded into a new runtime. It is permitted, but unusual, to create an anonymous bundle with a false name.
The natures of a bundle can change dynamically as new definitions are executed. To support this, bundles have an unusual metamorphic quality. The class bundle has seven direct subclasses; these eight classes correspond to the eight possible combinations of the three natures. All eight classes have identical structure, but they have different superclasses in addition to bundle that correspond to the natures that are active. When a nature is added to or removed from a bundle, its class morphs to the appropriate subclass of bundle or to bundle itself if all natures are removed.
bundle could have been defined by
def arity_name = set(#unary, #binary, #ternary, #prefix, #infix) defclass bundle(name name | false) name = name name | false ;; Class nature slots := [] list superclasses := [] list abstract := false boolean intrinsic := false boolean sealed := false boolean autothrow := false boolean noreturn := false boolean instance_description := false instance_description | false ;; Function nature methods := [] list requirements := [] list destructuring_method := false method | false ;; Operator nature arity := set[arity_name]() set[arity_name] left_precedence := 0 0..99 right_precedence := 0 0..99 ;; Macro facet of operator nature prefix_expander := false method | false infix_expander := false method | falseWe could save space by storing each nature in a subsidiary structure referenced by a pointer that is false when the nature is not present, but the slot-based interface would be the same, using . methods.
The three abstract nature superclasses are:
;; All class bundles inherit from this abstract: defclass class ;; All function bundles inherit from this, and so do methods and exit functions abstract: defclass function ;; All operator bundles inherit from this abstract: defclass operatorNone of these classes have slots.
The seven additional bundle classes are:
defclass class_bundle bundle, class defclass function_bundle bundle, function defclass class_function_bundle bundle, class, function defclass operator_bundle bundle, operator defclass class_operator_bundle bundle, class, operator defclass function_operator_bundle bundle, function, operator defclass class_function_operator_bundle bundle, class, function, operatorThese classes are not abstract, but they do not have constructors. A direct instance can only be created by morphing.
None of these classes are sealed. If you wish to use metaclass programming, you can define your own metaclass, which typically would inherit from class_function_bundle and cannot morph. A metaclass cannot inherit directly from class since it must be a bundle. A metaclass can add its own slots if desired.
The only use of metaclasses built into Lunar is for singleton classes. A singleton class is a subclass of class_bundle.
Previous page Table of Contents Next page