The p6opaque Responder Interface is the default responder for all Perl 6 objects.
Basics
This is a prototype-based OO system. It means that a class is simply an undefined object. The following assumptions help to understand it:
- $object.WHAT() === $prototype
- $object.HOW() === $prototype.HOW()
- $object.clone.WHAT() === $object.WHAT()
- $object.clone.HOW() === $object.HOW()
- $prototype.clone.HOW() !=== $prototype.HOW()
This stablishes the following relationships:
- Every object have a prototype
- Every object is defined
- Every prototype is undefined
- A prototype is its own prototype
- Every prototype have its own metaclass instance
- When cloning an object, the prototype information is cloned, therefore it points to the same prototype.
- When cloning a prototype, the metaclass information is cloned and it becomes a new prototype, therefore it has a different metaclass instance.
Implementation
- Both the prototype and the object are objects
- An object is composed by slots
- the slots in the object store what is described by the prototype
- the slots in the prototype describes the prototype
Composition
This is a hard topic in Perl 6, as compositions are mostly unpredictable (unless the class is closed). This way the composition is made with a "composition pile", where every composition operation is put in order, allowing correct method resolution. But the declarations in a class always override any composition declaration. That way, a prototype have:
- The composition pile (in order of composition)
- At compile time the order is:
- inheritance (reverse of the specified order)
- roles (in no particular order)
- At runtime the order is
- when composing with "is", it unshifts the pile
- when composing with "does", it pushes the pile
- The submethods
- The methods
- The attribute list (used during BUILD)
- Class storage
- each slot represents the class attributes' values
So the method lookup always:
- Looks for a member of the class
- goes bottom-up in the "composition pile" looking for the member
Private member lookup always:
- Look in the storage space for this class in the object
- Look in the class storage
An object, on the other hand, have only:
- Prototype reference
- One of the following
- Storage space for each participant of the composition (including the class itself), where each participant only sees its own space.
- each space contain slots for the attributes defined by that participant.
- WHENCE closure to autovivify this object.
p6opaque Structure
Putting this all together, we get to the following structure that every object, defined or not (in which case it is a prototype), have:
- metadata
- composition pile
- class storage
- class definitions
- class attributes
- my Int $.foo
- my Bool $!bar
- instance attributes
- has Int $.baz
- has Bool $!buz
- methods
- method foo() is rw as Int { ... }
- submethods
- instance storage
- WHENCE
If an object have empty storage, it's a protoobject, if it have a WHENCE it can be autovivified. A normal object will have only a single "is" in the compostition pile and all other metadata empty, on the other hand, it might also have other information, which makes it a self-contained object that is also its own class.