txt: ## primitives.md
  class Metamodel::Primitives
  
  Metaobject that supports low-level type operations
  
  ```raku
  class Metamodel::Primitives {}
  ```
  
  `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`](/type/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 `why`:
  
  ```raku
  my Mu $type := Metamodel::Primitives.create_type(Int.HOW, 'P6opaque');
  $type.^set_name('why oh why?');
  my %methods =  why => sub ($) { say 42 };
  Metamodel::Primitives.install_method_cache($type, %methods, :authoritative);
  $type.why;      # 42
  $type.list;
  CATCH { default { put .^name, ': ', .Str } };
  # 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:
  
  ```raku
  package Cache {
      our sub parameterize(+args) is raw {
          Metamodel::Primitives.parameterize_type: $?PACKAGE, args
      }
  
      sub noop(Mu, Mu \args) is raw {
          args
      }
  
      BEGIN Metamodel::Primitives.set_parameterizer: $?PACKAGE, &noop;
  }
  ```
  
  # [Methods](#class_Metamodel::Primitives "go to top of document")[§](#Methods "direct link")
  
  ## [method create\_type](#class_Metamodel::Primitives "go to top of document")[§](#method_create_type "direct link")
  
  ```raku
  method create_type(Mu $how, $repr = 'P6opaque')
  ```
  
  Creates and returns a new type from a metaobject `$how` and a representation name.
  
  ## [method set\_package](#class_Metamodel::Primitives "go to top of document")[§](#method_set_package "direct link")
  
  ```raku
  method set_package(Mu $type, $package)
  ```
  
  Sets the package associated with the type.
  
  ## [method install\_method\_cache](#class_Metamodel::Primitives "go to top of document")[§](#method_install_method_cache "direct link")
  
  ```raku
  method install_method_cache( Mu $type, %cache, :$authoritative = 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`](/type/X/Method/NotFound). If `:authoritative` is set to `False`, the usual fallback mechanism are tried.
  
  ## [method configure\_type\_checking](#class_Metamodel::Primitives "go to top of document")[§](#method_configure_type_checking "direct link")
  
  ```raku
  method configure_type_checking( Mu $type, @cache, :$authoritative = True, :$call_accepts = False )
  ```
  
  Configures the type checking for `$type`. `@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 `@cache`. If `:call_accepts` is True, the method [ACCEPTS](/routine/ACCEPTS) will be called for type checks against this type.
  
  ## [method configure\_destroy](#class_Metamodel::Primitives "go to top of document")[§](#method_configure_destroy "direct link")
  
  ```raku
  method configure_destroy(Mu $type, $destroy)
  ```
  
  Configures whether `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](#class_Metamodel::Primitives "go to top of document")[§](#method_compose_type "direct link")
  
  ```raku
  method compose_type(Mu $type, $configuration)
  ```
  
  Composes `$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](#class_Metamodel::Primitives "go to top of document")[§](#method_rebless "direct link")
  
  ```raku
  method rebless(Mu $object, Mu $type)
  ```
  
  Changes `$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 `$type`. [[1]](#fn1)
  
  ## [method is\_type](#class_Metamodel::Primitives "go to top of document")[§](#method_is_type "direct link")
  
  ```raku
  method is_type(Mu \obj, Mu \type --> Bool:D)
  ```
  
  Type-checks `obj` against `type`
  
  ## [method set\_parameterizer](#class_Metamodel::Primitives "go to top of document")[§](#method_set_parameterizer "direct link")
  
  ```raku
  method set_parameterizer(Mu \obj, &parameterizer --> Nil)
  ```
  
  Initializes the parameterization cache for a metaobject. This incorporates the `&parameterize` 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](#class_Metamodel::Primitives "go to top of document")[§](#method_parameterize_type "direct link")
  
  ```raku
  method parameterize_type(Mu \obj, +parameters --> Mu)
  ```
  
  Parameterizes a metaobject prepared by `set_parameterizer` with `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](#class_Metamodel::Primitives "go to top of document")[§](#method_type_parameterized "direct link")
  
  ```raku
  method type_parameterized(Mu \obj --> Mu)
  ```
  
  Returns the base metaobject from a parameterization given its resulting `obj`. Returns [`Mu`](/type/Mu) if none was ever performed.
  
  ## [method type\_parameters](#class_Metamodel::Primitives "go to top of document")[§](#method_type_parameters "direct link")
  
  ```raku
  method type_parameters(Mu \obj --> List:D)
  ```
  
  Returns the type arguments' object buffer from a parameterization given its resulting `obj`. Dies if none was ever performed.
  
  ## [method type\_parameter\_at](#class_Metamodel::Primitives "go to top of document")[§](#method_type_parameter_at "direct link")
  
  ```raku
  method type_parameter_at(Mu \obj, Int:D \idx --> Mu) is raw
  ```
  
  Returns a particular object from a parameterization given its resulting `obj` and an index, skipping the [`List`](/type/List)-building step of `type_parameters`. Dies if none was ever performed.
  
  1 [[↑]](#fnret1) As of Raku 2019.11, this method requires [special arrangements](https://github.com/rakudo/rakudo/issues/3414#issuecomment-573251877).
  