Metamodel::Primitives provides low-level operations for working with types, which are otherwise only available as implementation-dependent directives. These primitives are available as class methods.
Here is an example that steals the metamodel instance from the Int class to create a custom type (usually you would create your own metaclass if you mess with something as low-level), which allows calling of just one method called
my Mu := Metamodel::Primitives.create_type(Int.HOW, 'P6opaque');.^set_name('why oh why?');my = why => sub ($) ;Metamodel::Primitives.install_method_cache(, , :authoritative);.why; # 42.list;CATCH ;# OUTPUT: «X::Method::NotFound: Method 'list' not found for invocant of class 'why oh why?'␤»
Every metaobject has the capacity to hold a parameterization cache. This is distinct from the
parameterize metamethod backing parameterization syntax. For example, a package can be parametric in this low-level sense:
method create_type(Mu , = 'P6opaque')
Creates and returns a new type from a metaobject
$how and a representation name.
method set_package(Mu , )
Sets the package associated with the type.
method install_method_cache( Mu , , : = True)
Installs a method cache, that is, a mapping from method names to code objects. If
:authoritative is missing, or set to
True, then calls of methods that do not exist in the cache will throw an exception of type X::Method::NotFound. If
:authoritative is set to
False, the usual fallback mechanism are tried.
method configure_type_checking( Mu , , : = True, : = False )
Configures the type checking for
@cache is a list of known types against which
$type checks positively (so in a classical class-based system, the type itself and all recursive superclasses). If
:authoritative is missing or
True, this type will fail checks against all types not in
:call_accepts is True, the method ACCEPTS will be called for type checks against this type.
method configure_destroy(Mu , )
DESTROY methods are called (if present) when the garbage collector collects an object of this type (if
$destroy is set to a true value). This comes with a performance overhead, so should only be set to a true value if necessary.
method compose_type(Mu , )
$type (that is, finalizes it to be ready for instantiation). See https://github.com/Raku/nqp/blob/master/docs/6model/repr-compose-protocol.markdown for what
$configuration can contain (until we have better docs, sorry).
method rebless(Mu , Mu )
$object to be of type
$type. This only works if
$type type-checks against the current type of
$object, and if the storage of
$object is a subset of that of
method is_type(Mu \obj, Mu \type --> Bool)
method set_parameterizer(Mu \obj, --> Nil)
Initializes the parameterization cache for a metaobject. This incorporates the
¶meterize routine to produce parameterizations to be cached. This is assumed to carry a signature compatible with
:(Mu $root, List:D $args),
$root being the base metaobject for the parameterization,
$args being the type arguments' object buffer.
method parameterize_type(Mu \obj, +parameters --> Mu)
Parameterizes a metaobject prepared by
parameters. The resulting metaobject is cached by literal object comparisons with
=:= for each element of
parameters. Containers tend to invalidate any match.
method type_parameterized(Mu \obj --> Mu)
Returns the base metaobject from a parameterization given its resulting
Mu if none was ever performed.
method type_parameters(Mu \obj --> List)
Returns the type arguments' object buffer from a parameterization given its resulting
obj. Dies if none was ever performed.
method type_parameter_at(Mu \obj, Int \idx --> Mu) is raw
Returns a particular object from a parameterization given its resulting
obj and an index, skipping the
List-building step of
type_parameters. Dies if none was ever performed.