<commit_before># Copyright (C) 2001-2007, The Perl Foundation.
# $Id$

=head1 NAME

docs/pdds/pdd17_pmc.pod - Parrot Magic Cookies

=head1 VERSION

$Revision$

=head1 ABSTRACT

This PDD describes the internal structure and behavior of the Parrot Magic
Cookie (PMC) data type. 


=head1 DESCRIPTION

PMCs implement all internal data types more complex than a simple integer,
float, or string, and also the data types of high-level languages.  Nothing
outside the core of Parrot (in fact, nothing outside the data type's vtable
routines) should infer anything about a PMC (hence the Magic part).

This does mean, though, that you need to either know
what functions are available and what they do, or have some method of finding
out. 

It's faster if you know which vtable entry does what, so that's the method
parrot uses.


=head1 QUESTIONS

=over 4

=item *

Where should c-level role implementations live? In src/pmc? What naming
convention should we use for the files? Singleton role goes to rsingleton.pmc?

=item *

Should we create a pmrole keyword like pmclass? And pmr2c to translate them to
C? How different are classes and roles at the PMC level?

=item *

<particle> pmclass needs a keyword to specify what roles a class is composed
from.  We're already using 'does', but in an ad hoc way, from what I can see in
the little docs there are about 'does'.

=item *

<particle> Do c-level roles have custom flags like PMCs? Class PMC has a custom
flag for 'instantiated', right now it uses a full int, which I think is a waste
of space. <allison> 8 bits is pretty limited, and IIRC we've already run into
the limitation. This runs back to Leo's proposal to make PMCs a little more
flexible, so we wouldn't have to hold all PMCs to the same 8 bits

=item *

<pmichaud> there is a question about when 'Integer' is not really .Integer
e.g., in a HLL, the meaning of 'Integer' can be different, and using C<new
'Integer'> is safe only if in the root of the parrot HLL namespace

<allison> true, the only way to guarantee that you're getting a built-in PMC
under the type id-less system is to look in the 'parrot' HLL, and even that
isn't a total guarantee, because it could have been replaced in the 'parrot'
HLL

<pmichaud> the closest we have at the moment is

  $P0 = get_root_namespace ['parrot'; 'Integer']
  $P1 = new $P0

but even this assumes that the 'Integer' namespace is tied to the Integer
class, which also hasn't been specced

<allison> builtin PMCs will be tied to a corresponding spot in the 'parrot' HLL
namespace

<pmichaud> according to pdd15: C<$P0 = new .Integer> can be replaced by C<$P0 =
new 'Integer'> only in the parrot root namespace. in all other
namespaces, one would need to get the namespace for the 'Integer' class and use
that

  $P0 = new 'Integer' # works in parrot HLL, root namespace
  $P0 = new ['Integer'] # works in parrot HLL, any namespace

<pmichaud> even easier, HLLs can set their notion of 'Integer' to point to the
parrot class :-)

<allison> yes, aliasing across namespaces is allowed

=item *

<particle> we can design a decoration for core pmcs with something that doesn't
allow override in 'parrot' namespace, if it's wanted.

<pmichaud> particle: I'm not sure it's entirely necessary to have the
decoration i.e., I'd wait until we find we need it :-)

<particle> sure, it's mostly a change for pmc2c i suspect

  pmclass Foo does bar extends baz is_core {

=item *

ResizablePMCArray returns Undef for unset elements (so does the new object
model, because it uses ResizablePMCArray for storage), but Hash returns null.
Various other PMCs return different values for undefinedness.  Pick a standard.
The current favorite is a singleton Null PMC. Check the implementation of
PMCNULL.

=item *

<chromatic> How does COW work and why doesn't COW work? (docs/glossary.pod)

=back

=head1 DESCRIPTION

=over 4

=item - High-level objects can subclass low-level PMCs

=back

=head1 IMPLEMENTATION

=head2 Internal structure

All PMCs have the form:

    struct PMC {
        pobj_t obj;
        VTABLE *vtable;
        PMC *real_self;
 #if ! PMC_DATA_IN_EXT
        DPOINTER *data;
 #endif
        struct PMC_EXT *pmc_ext;
    };

where C<obj> is a pointer to a C<pobj_t> structure:

    typedef struct pobj_t {
        UnionVal u;
        Parrot_UInt flags;
    } pobj_t;

and where:

    typedef union UnionVal {
        struct {
            void * _bufstart;
            size_t _buflen;
        } _b;
        struct {
            DPOINTER* _struct_val;
            PMC* _pmc_val;
        } _ptrs;
        INTVAL _int_val;
        FLOATVAL _num_val;
        struct parrot_string_t * _string_val;
    } UnionVal;

C<u> holds data associated with the PMC. This can be in the form of an integer
value, a floating-point value, a string value, or a pointer to other data.
C<u> may be empty, since the PMC structure also provides a more general data
pointer, but is useful for PMCs which hold only a single piece of data (e.g.
C<PerlInts>).

C<flags> holds a set of flags associated with the PMC; these are documented  in
F<include/parrot/pobj.h>, and are generally only used within the Parrot 
internals.

C<vtable> holds a pointer to the B<vtable> associated with the PMC. This points
to a set of functions, with interfaces described in
L<Vtable Functions> that implement the basic behaviour of the PMC
(i.e. how it behaves under addition, subtraction, cloning etc.)

{{ PROPOSED:
C<real_self> holds a pointer to the PMC that dynamically dispatched method
calls should be made on. Normally this will be a pointer directly back to the
PMC itself. However, in the case that the PMC has been subclassed by a non-PMC
it will hold a pointer to the real object. This is so DYNSELF.method() style
calls will dispatch correctly, calling any methods and/or v-table methods that
have been overridden in PIR.

AR: Problem is, not all low-level PMCs have a PMCProxy that could be stored in
real_self to handle these method calls (they're only created when the subclass
is created). So, rather than storing real_self for all PMCs, we should only
store the delegator for objects that are delegated to (whether they're proxied
or otherwise delegated).

AR: Alternatively, this magic could all live in the PMCProxy: look up the
method object, and then invoke it passing in the delegator as the invocant.
(Not practical, because the code from the delegated class will expect to be
poking into the internals of the object, but will have the wrong object.)
Alternatively, we could say that PMCProxies must create PDD15 style storage for
the delegated class. (Not practical, because the delegated class methods will
expect to be poking into the internals of the object, but will have the wrong
object.)

}}

C<data> (if present) holds a pointer to any additional data associated  with
the PMC. This may be NULL.

C<pmc_ext> points to an extended PMC structure. This has the form:

    struct PMC_EXT {
 #if PMC_DATA_IN_EXT
        DPOINTER *data;
 #endif
        PMC *_metadata;             # [Note: replaced by roles]
        struct _Sync *_synchronize; # [Note: may be deprecated, see STM]
        PMC *_next_for_GC;
    };

C<data> is a generic data pointer, as described above.

C<_metadata> holds internal PMC metadata. The specification for this has not
yet been finalized.

C<_synchronize> is for access synchronization between shared PMCs.

C<_next_for_GC> determines the next PMC in the 'used' list during dead object 
detection in the GC.

PMCs are not required to have a C<PMC_EXT> structure (i.e. C<pmc_ext> can be
null).

PMCs are used to implement the basic data types of the high level languages
running on top of Parrot. For instance, a Perl 5 C<SV> will map onto one (or
more) types of PMC, while particular Python datatypes will map onto different
types of PMC.

=head2 Interaction between PMCs and high-level objects

{{ Address the problem of high-level objects inheriting from low-level PMCs,
and any structural changes to low-level PMCs that might require. }}

High-level objects, as specified in PDD15, need to be able to inherit from
PMCs. This is achieved through the combination of a C<PMCProxy> PMC and
delegation.

For PDD15 objects, there is a corresponding instance of the C<Class> PMC. For
a PMC, however, the class definition is written in C and compiled away. There
needs to be something that can be placed in the parents list for a PDD15
class. That something is the C<PMCProxy> PMC. Like a PDD15 class, it is
stored as the C<class> element in the namespace associated with a PMC, provides
introspection facilities and can sit in an inheritance hierarchy.

The PMCProxy PMCs are only created when needed for subclassing a low-level
PMC, to avoid a large load of unused PMCProxy objects. When created, they are
cached in the class slot of the namespace corresponding to the low-level PMC,
so they are only created once.

Therefore, subclassing a PMC looks, at a PIR level, like subclassing a high
level class.

  $P0 = get_class 'Hash'
  $P1 = newclass 'MyClass'
  addparent $P1, $P0     # The new class inherits from the Hash PMC

Or, more briefly:

  $P1 = subclass 'Hash', 'MyClass'

PMCs store state in a very different way to PDD15 objects. When a method
inherited from a PMC is called on a PDD15 object, that method needs to get
a chunk of state that it can use as it wishes. Further to this, if multiple
PMCs are inherited from, they may use the state in different ways. Users of
Parrot at a PIR level should not have to care about such issues.

(AR: I'm willing to make some changes in how low-level PMCs store state in
order to make this easier.)

Therefore, when a PDD15 object is instantiated and it inherits from PMCs, an
instance of each of the PMCs that it inherits from is also created. These are
stored at the end of the object's attributes store.

When a method is called on an object whose class has PMC parents, the call is
delegated up to each of the PMC parents, in MRO order. The invocant must be
the appropriate PMC instance from the object's attribute store. For v-table
calls, this is just a case of passing the correct thing. For other methods
that are located by C<find_method>, a C<Bound_NCI> PMC is used to ensure that
the method from the PMC is invoked with the correct instance, so it has access
to the correct state.

(AR: Why isn't it called directly on the delegated PMC stored in the delegating
object's data store?)

When a PMC calls a method on itself, it may have been overridden in a high
level class. Therefore dynamic dispatches of method calls need to be done with
the vtable of the high level class, not the vtable of the PMC itself.

For PMCs that are instantiated and not overridden, the C<real_self> pointer in
the PMC structure is a reference to the PMC instance itself. If, however, it
is just acting to provide the state a PMC needs but is not the real instance,
this pointer will point to the instance of the high level class (an instance
of the C<Object> PMC). Method dispatches using C<DYNSELF> will always go
through this mechanism.

(AR: See comment above about delegated calls. Better to have the delegator
object only exist for delegated PMCs, and have DYNSELF check for it.)

Attribute access is, like method access, delegated upwards. Since attribute
lookup is a vtable method, the down case is covered by the previous paragraph.

(AR: What about overriding a low-level attribute with a high-level attribute?
Can you override the core data store of a Hash? The core struct members of an
STMLog? This would be a lot easier if low-level PMCs had a standard way of
defining their attributes (core struct members), which could be used to
generate struct declarations, to automatically fill a PMC's C<inspect>,
C<get_attr>, and C<set_attr> vtable functions, to annotate PMCProxy objects,
and to allow state for compile-time roles to be generated in the same struct as
state from the PMC itself.)

}}

If a low-level PMC expects to be overridden by high-level classes (which means
all the core low-level PMC types), it must respect a standard interface. It
must implement the C<get_attr> and C<set_attr> vtable entries for any core
attributes it expects to be accessible to subclasses.

Subclassing a low-level class from a high-level class makes an entry in the
high-level class's list of parents. This entry is a proxy class object for the
low-level PMC class that provides access to the low-level PMC's vtable
(including the implementations of get_attr and set_attr), and defines the
storage that the low-level object will need within the high-level object (this
could be as simple as a single integer attribute that gives an index into the
object's data store where an instance of the low-level class is stored).


=head1 REFERENCE

=head2 Vtable Functions

Vtables decouple the interface and implementation of various object functions. 
The actual vtable structure contains pointers to functions that implement the
methods for that particular PMC.  All pointers must point to valid functions
with appropriate prototypes.

In C code, the first parameter to any vtable routine is the current
interpreter. The second parameter is the PMC itself.

The following list details each of the vtable methods, their prototypes, and
their behavior.

=head3 Core Vtable Functions

=over 4

=item init

  void init(INTERP, PMC* self)

Called when a PMC is first instantiated. It takes an unused PMC parameter and
turns it into a PMC of the appropriate class.

=item init_pmc

  void init_pmc(INTERP, PMC* self, PMC* initializer)

Alternative entry point called when a PMC is first instantiated.  Accepts a PMC
parameter used to initialize the given object.  Interpretation of the PMC
initializer is left open, each PMC is free to choose its own implemention. A
NULL value passed as the initializer parameter is allowed.

NOTE: It is strongly suggested that init_pmc(PMCNULL) be equivalent to
init(), though there will of necessity be exceptions.

=item morph

  void morph(INTERP, PMC* self, INTVAL type)

Turn the PMC into a PMC of type I<type>. If the morphing can't be done in any
reasonable way -- for instance if an integer is asked to turn into an Array --
then the PMC is first destroyed, then recreated as an empty PMC of the new
type.

This method is primarily used when the interpreter has need of coercing a PMC
to a particular type, and isn't meant as a general purpose casting tool.
Compilers should only emit valid morphing operations.

=item mark

  void mark(INTERP, PMC* self)

Called when the DOD is tracing live PMCs. If this method is called then the
code must mark all strings and PMCs that it contains as live, otherwise they
may be collected.

This method is only called if the DOD has detected that this PMC is both alive
and has a custom mark routine as indicated by the custom mark PMC flag.  (Most
normal PMCs don't need a custom mark routine.)

If a PMC has this flag set, then it is responsible for marking all buffers and
PMCs under its control as alive. If it does not, those PMCs or buffers may be
collected later. This method does I<not> have to call the C<mark> method on any
PMCs it marks--the DOD system takes care of that. (So no need to recurse into
aggregate PMCs or anything of the sort).

This method may allocate no memory from Parrot, nor may it alter Parrot's
internal structures. It should have no side-effects from the C level either.
This routine may not throw an exception.

=item destroy

  void destroy(INTERP, PMC* self)

Called when the PMC is destroyed. This method is called by the DOD when it
determines that a PMC is dead and that the PMC has marked itself as having a
destroy method (an active finalizer).

When this method finishes, the PMC will be marked as dead. As such you should
make sure that you don't leave any references to it in any Parrot structure
by the end of the method.

This method may not throw an exception. It will be ignored if it does.

=item clone

  PMC* clone(INTERP, PMC* self)

Return a clone of a PMC.

=item defined

  INTVAL defined(INTERP, PMC* self)

Return a true value if the PMC is defined, false otherwise.

=back

=head3 Accessors

=over 4

=item getprop

  PMC* getprop(INTERP, PMC* self, STRING* key)

Return the value from the property hash of I<self> keyed by I<key>. The key
should not be NULL.

=item setprop

  void setprop(INTERP, PMC* self, STRING* key, PMC* value)

Set the value in the property hash of I<self> that is keyed by I<key> to the
value of I<value>. The key should not be NULL.

=item delprop

  void delprop(INTERP, PMC* self, STRING* key)

Delete the value from the property hash of I<self> keyed by I<key>. The key
should not be NULL.

=item getprops

  PMC* getprops(INTERP, PMC* self)

Return the entire property hash for I<self>.

=item type

  INTVAL type(INTERP, PMC* self)

Return the type of the PMC. Type is a unique number associated with the PMC when
the PMC's class is loaded. Negative numbers are considered
interpreter-specific, non-public types. [NOTE: will be deprecated when type IDs
are deprecated.]

=item subtype

  UINTVAL subtype(INTERP, PMC* self, INTVAL type) [deprecated]

Return the subtype of a PMC. (Note that this may be unimplemented, and may go
away). This is intended to return information about the PMC--what type of
number or string it is, whether it's a scalar, hash, array, or list, and
suchlike things.

[This can be adequately handled by C<does> and C<inspect>.]

=item name

  STRING* name(INTERP, PMC* self)

Return the name of the class for the PMC.

=item get_integer

  INTVAL get_integer(INTERP, PMC* self)

Return the native integer value of the PMC.

=item get_number

  FLOATVAL get_number(INTERP, PMC* self)

Return the native floating-point value of the PMC.

=item get_bignum

  PMC* get_bignum(INTERP, PMC* self)

Return the extended precision numeric value of the PMC as a new bignum PMC.

=item get_string

  STRING* get_string(INTERP, PMC* self)

Return the native string value of the PMC. This may be in any encoding, chosen
by the PMC.

=item get_bool

  INTVAL get_bool(INTERP, PMC* self)

Return the true/false value of the PMC (the constant TRUE or the constant
FALSE). The definition of truth for a given PMC will depend on the type of the
PMC. For a scalar, it may be as simple as returning false when the PMC has a
value 0 or "", and returning true when the PMC has any other value.

=item get_pmc

  PMC* get_pmc(INTERP, PMC* self)

Return the PMC value for this PMC. This is useful in circumstances where the
thing being accessed may return something other than its own value. For
example, an array might return a reference to itself. Any PMC may return a
value different from the PMC that C<get_pmc> is being called on.

=item set_integer_native

  void set_integer_native(INTERP, PMC* self, INTVAL value)

Set the integer value of this PMC from a native integer value (integer
register/constant).

=item set_integer_same

  void set_integer_same(INTERP, PMC* self, PMC* value)

Set the value of this PMC from the integer value of another PMC. The value PMC
is guaranteed to be of the same type as the I<self> PMC, so optimizations may
be made.

=item set_number_native

  void set_number_native(INTERP, PMC* self, FLOATVAL value)

Set the value of this PMC from a native floating-point value (float
register/constant).

=item set_number_same

  void set_number_same(INTERP, PMC* self, PMC* value)

Set the value of this PMC from the floating-point value another PMC. The value
PMC is guaranteed to be of the same type as the I<self> PMC, so optimizations
may be made.

=item get_pointer

  void* get_pointer(INTERP, PMC* self)

Returns a pointer value for the PMC. Useful for PMCs that hold pointers to
arbitrary data. The details of the data (type, location etc.) depend on the
PMC.

=item set_bignum_int

  void set_bignum_int(INTERP, PMC* self, INTVAL value)

Morph the PMC to a BIGNUM PMC, and set the extended-precision value from a
native integer.

=item set_string_native

  void set_string_native(INTERP, PMC* self, STRING* value)

Set the value of this PMC from a native string value (string
register/constant).

=item assign_string_native

  void assign_string_native(INTERP, PMC* self, STRING* value)

Set the value of this PMC to a copied native string value (string
register/constant).

=item set_string_same

  void set_string_same(INTERP, PMC* self, PMC* value)

Set the value of this PMC from the string value of another PMC. The value PMC
is guaranteed to be of the same type as the I<self> PMC, so optimizations may
be made.

=item set_bool

  void set_bool(INTERP, PMC* self, INTVAL value)

Set the boolean state of the PMC to TRUE if the native integer value passed in
is TRUE, or FALSE if the value is FALSE. The definition of truth is left open
to the particular PMC. For a scalar, it may be as simple as setting false when
a 0 value is passed in, and seting true when any other value is passed in.

=item assign_pmc

  void assign_pmc(INTERP, PMC* self, PMC* value)

Set the value of the PMC in I<self> to the value of the PMC in I<value> by
copying the value.

=item set_pmc

  void set_pmc(INTERP, PMC* self, PMC* value)

Make the PMC in I<self> refer to the PMC passed as I<value>.

=item set_pointer

  void set_pointer(INTERP, PMC* self, void* value)

Set the pointer value of the PMC Useful for PMCs that hold pointers to
arbitrary data. The details of the data (type, location etc.) depend on the
PMC.

=back

=head3 Aggregate Vtable Functions

Many of the following functions have a *_keyed form, a *_keyed_int form, and a
*_keyed_str form. The keyed forms take a PMC*, INTVAL, or STRING* key as a
parameter. The PMC* parameter is NULL if there is no key for that
PMC; this means that that argument is unkeyed.

In some cases, the caller must provide a non-NULL key.  Those cases are
explicitly stated below.  In the other cases, you may have to implement the
keyed vtable functions and check for a NULL I<self> key even if you are
implementing a non-aggregate type.  If the I<self> key is non-NULL and the PMC
class is a non-aggregate type, the _keyed_* methods should throw an exception.

If you do not implement the *_keyed_int and *_keyed_str functions, the default
will convert the INTVAL or STRING* into a key PMC* and call the corresponding
*_keyed functions.

=over 4

=item elements

  INTVAL elements(INTERP, PMC* self)

Return the number of elements in the PMC.

=item get_integer_keyed

  INTVAL get_integer_keyed(INTERP, PMC* self, PMC* key)

Return the integer value for the element indexed by a PMC key.  The key is
guaranteed not to be NULL for this function.

=item get_integer_keyed_int

  INTVAL get_integer_keyed_int(INTERP, PMC* self, INTVAL key)

Return the integer value for the element indexed by an integer key.  The key is
guaranteed not to be NULL for this function.

=item get_integer_keyed_str

  INTVAL get_integer_keyed_str(INTERP, PMC* self, STRING* key)

Return the integer value for the element indexed by a string key.  The key is
guaranteed not to be NULL for this function.

=item get_number_keyed

  FLOATVAL get_number_keyed(INTERP, PMC* self, PMC* key)

Return the native floating-point value for the element indexed by a PMC key.
The key is guaranteed not to be NULL for this function.

=item get_number_keyed_int

  FLOATVAL get_number_keyed_int(INTERP, PMC* self, INTVAL key)

Return the native floating-point value for the element indexed by an integer
key. The key is guaranteed not to be NULL for this function.

=item get_number_keyed_str

Return the native floating-point value for the element indexed by a string key.
The key is guaranteed not to be NULL for this function.

=item get_string_keyed

  STRING* get_string_keyed(INTERP, PMC* self, PMC* key)

Return the string value for the element indexed by a PMC key.
The key is guaranteed not to be NULL for this function.

=item get_string_keyed_int

  STRING* get_string_keyed_int(INTERP, PMC* self, INTVAL key)

Return the string value for the element indexed by an integer key.
The key is guaranteed not to be NULL for this function.

=item get_string_keyed_str

  STRING* get_string_keyed_str(INTERP, PMC* self, STRING* key)

Return the string value for the element indexed by a string key.
The key is guaranteed not to be NULL for this function.

=item get_bool_keyed

Return the boolean value for the element indexed by a PMC key.

=item get_bool_keyed_int

Return the boolean value for the element indexed by an integer key.

=item get_bool_keyed_str

Return the boolean value for the element indexed by a string key.

=item get_pmc_keyed

  PMC* get_pmc_keyed(INTERP, PMC* self, PMC* key)

Return the PMC value for the element indexed by a PMC key.
The key is guaranteed not to be NULL for this function.

=item get_pmc_keyed_int

  PMC* get_pmc_keyed_int(INTERP, PMC* self, INTVAL key)

Return the PMC value for the element indexed by an integer key.
The key is guaranteed not to be NULL for this function.

=item get_pmc_keyed_str

  PMC* get_pmc_keyed_str(INTERP, PMC* self, STRING* key)

Return the PMC value for the element indexed by a string key.
The key is guaranteed not to be NULL for this function.

=item get_pointer_keyed

  void* get_pointer_keyed(INTERP, PMC* self, PMC* key)

Return the pointer value for the element indexed by a PMC key. The details of
the data (type, location etc.) depend on the PMC.

=item get_pointer_keyed_int

  void* get_pointer_keyed_int(INTERP, PMC* self, INTVAL key)

Return the pointer value for the element indexed by an integer key. The
details of the data (type, location etc.) depend on the PMC.

=item get_pointer_keyed_str

  void* get_pointer_keyed_str(INTERP, PMC* self, STRING* key)

Return the pointer value for the element indexed by a string key. The details
of the data (type, location etc.) depend on the PMC.

=item set_integer_keyed

  void set_integer_keyed(INTERP, PMC* self, PMC* key, INTVAL value)

Set the integer value of the element indexed by a PMC key. The key is
guaranteed not to be NULL for this function.

=item set_integer_keyed_int

  void set_integer_keyed_int(INTERP, PMC* self, INTVAL key, INTVAL value)

Set the integer value of the element indexed by an integer key. The key is
guaranteed not to be NULL for this function.

=item set_integer_keyed_str

  void set_integer_keyed_str(INTERP, PMC* self, STRING* key, INTVAL value)

Set the integer value of the element indexed by a string key. The key is
guaranteed not to be NULL for this function.

=item set_number_keyed

  void set_number_keyed(INTERP, PMC* self, PMC* key, FLOATVAL value)

Set the floating-point value of the element indexed by a PMC key. The key is
guaranteed not to be NULL for this function.

=item set_number_keyed_int

  void set_number_keyed_int(INTERP, PMC* self, INTVAL key, FLOATVAL value)

Set the floating-point value of the element indexed by an integer key. The key
is guaranteed not to be NULL for this function.

=item set_number_keyed_str

  void set_number_keyed_str(INTERP, PMC* self, STRING* key, FLOATVAL value)

Set the floating-point value of the element indexed by a string key. The key
is guaranteed not to be NULL for this function.

=item set_string_keyed

  void set_string_keyed(INTERP, PMC* self, PMC* key, STRING* value)

Set the string value of the element indexed by a PMC key.  The key is
guaranteed not to be NULL for this function.

=item set_string_keyed_int

  void set_string_keyed_int(INTERP, PMC* self, INTVAL key, STRING* value)

Set the string value of the element indexed by an integer key.  The key is
guaranteed not to be NULL for this function.

=item set_string_keyed_str

  void set_string_keyed_str(INTERP, PMC* self, STRING* key, STRING* value)

Set the string value of the element indexed by a string key.  The key is
guaranteed not to be NULL for this function.

=item set_pmc_keyed

  void set_pmc_keyed(INTERP, PMC* self, PMC* key, PMC* value)

Set the value of the element indexed by a PMC key, by copying the value of
another PMC.

=item set_pmc_keyed_int

  void set_pmc_keyed_int(INTERP, PMC* self, INTVAL key, PMC* value)

Set the PMC value of the element indexed by an integer key, by copying the
value of another PMC.

=item set_pmc_keyed_str

  void set_pmc_keyed_str(INTERP, PMC* self, STRING* key, PMC* value)

Set the PMC value of the element indexed by a string key, by copying the value
of another PMC.

=item set_pointer_keyed

  void set_pointer_keyed(INTERP, PMC* self, PMC* key, void* value)

Set the pointer value of the element indexed by a PMC key.

=item set_pointer_keyed_int

  void set_pointer_keyed_int(INTERP, PMC* self, INTVAL key, void* value)

Set the pointer value of the element indexed by an integer key.

=item set_pointer_keyed_str

  void set_pointer_keyed_str(INTERP, PMC* self, STRING* key, void* value)

Set the pointer value of the element indexed by a string key.

=item type_keyed

  INTVAL type_keyed(INTERP, PMC* self, PMC* key)

Return the type number of the PMC indexed by a PMC key.  The I<key> parameter
is guaranteed not to be NULL for this method. [NOTE: To be deprecated when type
IDs are deprecated.]

=item type_keyed_int

  INTVAL type_keyed_int(INTERP, PMC* self, INTVAL key)

Return the type number of the PMC indexed by an integer key.  The I<key>
parameter is guaranteed not to be NULL for this method. [NOTE: To be deprecated
when type IDs are deprecated.]

=item type_keyed_str

  INTVAL type_keyed_str(INTERP, PMC* self, STRING* key)

Return the type number of the PMC indexed by a string key.  The I<key>
parameter is guaranteed not to be NULL for this method. [NOTE: To be deprecated
when type IDs are deprecated.]

=item pop_integer

  INTVAL pop_integer(INTERP, PMC* self)

Return the integer value of the last item on the list, removing that item.

=item pop_float

  FLOATVAL pop_float(INTERP, PMC* self)

Return the floating-point value of the last item on the list, removing that
item.

=item pop_string

  STRING* pop_string(INTERP, PMC* self)

Return the string value of the last item on the list, removing that item.

=item pop_pmc

  PMC* pop_pmc(INTERP, PMC* self)

Return the PMC value of the last item on the list, removing that item.

=item push_integer

  void push_integer(INTERP, PMC* self, INTVAL value)

Add the passed in integer value to the end of the list.

=item push_float

  void push_float(INTERP, PMC* self, FLOATVAL value)

Add the passed in floating-point number to the end of the list.

=item push_string

  void push_string(INTERP, PMC* self, STRING* value)

Add the passed in string to the end of the list.

=item push_pmc

  void push_pmc(INTERP, PMC* self, PMC* value)

Add the passed in PMC to the end of the list.

=item shift_integer

  INTVAL shift_integer(INTERP, PMC* self)

Return the integer value of the first item on the list, removing that item.

=item shift_float

  FLOATVAL shift_float(INTERP, PMC* self)

Return the floating-point value of the first item on the list, removing that
item.

=item shift_string

  STRING* shift_string(INTERP, PMC* self)

Return the string value of the first item on the list, removing that item.

=item shift_pmc

  PMC* shift_pmc(INTERP, PMC* self)

Return the PMC value of the first item on the list, removing that item.

=item unshift_integer

  void unshift_integer(INTERP, PMC* self, INTVAL value)

Add the passed in integer value to the beginning of the list.

=item unshift_float

  void unshift_float(INTERP, PMC* self, FLOATVAL value)

Add the passed in floating-point number to the beginning of the list.

=item unshift_string

  void unshift_string(INTERP, PMC* self, STRING* value)

Add the passed in string to the beginning of the list.

=item unshift_pmc

  void unshift_pmc(INTERP, PMC* self, PMC* value)

Add the passed in PMC to the beginning of the list.

=item splice

  void splice(INTERP, PMC* self, PMC* value, INTVAL offset, INTVAL count)

Replace the I<count> PMCs at offset I<offset> from the beginning of I<self>
with the PMCs in the aggregate I<value>.

=item exists_keyed

=item exists_keyed_int

=item exists_keyed_str

=item defined_keyed

=item defined_keyed_int

=item defined_keyed_str

=item dtem delete_keyed_str

=item nextkey_keyed

=item nextkey_keyed_itr_str

=back

=head3 Math Vtable Functions

=over 4

=item add

  void add(INTERP, PMC* self, PMC* value, PMC* dest)
  void add_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void add_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Add the value of I<self> to the value of a PMC, native integer, or native
floating-point number and store the result in a PMC I<dest>. Note that I<dest>
may be the same PMC as I<self>; in that case optimizations may be made.

=item subtract

  PMC* subtract(INTERP, PMC* self, PMC* value, PMC* dest)
  PMC* subtract_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  PMC* subtract_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Subtract the value of a PMC, native integer, or native floating-point number
from a PMC and store the result in I<dest>. If I<dest> is NULL create a result
PMC of an appropriate type.  Note that I<dest> may be the same PMC as I<self>;
in that case optimizations may be made.

=item i_subtract

  void i_subtract(INTERP, PMC* self, PMC* value)
  void i_subtract_int(INTERP, PMC* self, INTVAL value)
  void i_subtract_float(INTERP, PMC* self, FLOATVAL value)

Inplace operation: subtract a PMC, native integer, or native floating-point
number from the value of a PMC and store the result back in the same PMC.

=item increment

=item decrement

=item multiply

  void multiply(INTERP, PMC* self, PMC* value, PMC* dest)
  void multiply_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void multiply_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Multiply a PMC, native integer, or floating-point value by the value of the PMC
I<self> and store the result in the I<dest> PMC. Note that I<dest> may be the
same PMC as I<self>; in that case optimizations may be made.

=item divide

  void divide(INTERP, PMC* self, PMC* value, PMC* dest)
  void divide_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void divide_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Divide the value of the I<self> PMC by a PMC, native integer, or native
floating-point number and store the result in I<dest>.  Note that I<dest> may
be the same PMC as I<self>; in that case optimizations may be made.

=item modulus

  void modulus(INTERP, PMC* self, PMC* value, PMC* dest)
  void modulus_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void modulus_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Divide the value of the I<self> PMC by the value of a PMC, native integer, or
native floating-point number and store the remainder in I<dest>.  Note that
I<dest> may be the same PMC as I<self>; in that case optimizations may be made.

=item cmodulus

  void cmodulus(INTERP, PMC* self, PMC* value, PMC* dest)
  void cmodulus_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void cmodulus_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Divide the value of the I<self> PMC by the value of a PMC, native integer, or
native floating-point number and store the remainder in I<dest>.  Note that
I<dest> may be the same PMC as I<self>; in that case optimizations may be made.

Note that C<modulus> uses Knuth's "corrected mod" algorithm, as implemented in
F<src/utils.c>, while C<cmodulus> uses the C-style fmod function.

=item neg

  void neg(INTERP, PMC* self, PMC* dest)

Negate the sign of I<self> and store the result in I<dest>. Note that I<self>
and I<dest> may refer to the same PMC, in which case optimizations may be
made.

=back

=head3 Logical Vtable Functions

=over 4

=item bitwise_or

  void bitwise_or(INTERP, PMC* self, PMC* value, PMC* dest)
  void bitwise_or_int(INTERP, PMC* self, INTVAL value, PMC* dest)

Calculate the bitwise-OR of the value of the I<self> PMC and the value of a PMC
or native integer and store the result in I<dest>. Note that I<dest> may be the
same PMC as I<self>; in that case optimizations may be made.
[Question: what happens when the I<self> and I<value> PMCs aren't integers?]

=item bitwise_and

=item bitwise_and_int

=item bitwise_xor

=item bitwise_xor_int

=item bitwise_ors

=item bitwise_ors_str

=item bitwise_ands

=item bitwise_ands_str

=item bitwise_xors

=item bitwise_xors_str

=item bitwise_not

=item bitwise_shl

=item bitwise_shl_int

=item bitwise_shr

=item bitwise_shr_int

=item is_equal

=item is_same

=item cmp

=item cmp_num

=item cmp_string

=item logical_or

=item logical_and

=item logical_xor

=item logical_not

=back

=head3 String Vtable Functions

=over 4

=item concatenate

=item concatenate_native

=item repeat

=item repeat_int

=back

=head3 Code Vtable Functions

=over 4

=item invoke

=item fsh

=item visit

=item share

=back

=head3 Class/Object Vtable Functions

=over 4

=item can

=item does

=item isa

=item add_method

=item add_attribute

=item get_attr

=item set_attr

=item add_parent

=item add_role

=item PMC* find_method(INTERP, PMC* self, STRING* method_name)

Return a subroutine PMC for the passed method name. This subroutine PMC may be
cached, so the method I<must> return an equivalent sub PMC each time, or be
capable of dealing with the returned sub PMCs being reused. [Why should it be
cached? Can you turn off caching? What if you want to override find_method to
generate methods on the fly?]


=back



=head2 Core PMCs

Parrot has a number of core PMC types that all programs can guarantee will be
available to them. (With the possible exception of Parrot programs executing on
an embedded device or other restricted environment)

=head3 Scalar types

=over 4

=item Undef

This is the generic no-value type. It has a numeric value of zero, a string
value of empty string, and a boolean value of false. It will, on assignment,
turn itself into a PMC of the source type, or if assigned a basic type will
turn itself into one of the wrapper PMC types (detailed below) for the basic
types.

=item Integer

The PMC wrapper for Parrot's low-level integer type. Always an integer, with
other types auto-converted to an integer when stored into this PMC. The range
and behaviour of the Integer PMC is identical to the platform low-level
integer.

The boolean value for an Integer is false if zero, otherwise true.

Floating point, string, and bignum values assigned to an Integer PMC round to
the nearest integer. Floats, or strings which resolve to numbers, cap at the
platform maximum or minimum integer value.

Integer PMCs take on a value of 1 if a boolean true is assigned, and a value of
0 if a boolean false is assigned.

If an out-of-range value is assigned to an Integer PMC, the PMC will throw an
exception if exact math is enabled.

=item Float

The PMC wrapper for Parrot's low-level floating-point type. Always a float,
with other types autoconverted to a float when stored into this PMC.

The boolean value for a Float is false if exactly zero, otherwise true.

When converted to an integer, floats round to the closest integer, capping at
the platform maximum or minimum integer value.

When converting to a string, floats use the platform default snprintf format.

=item String

The PMC wrapper for Parrot's low-level string type. Always a simple string,
with other types autoconverted to a string when stored into this PMC.

The boolean value for a String is false if empty or the string '0' (a one
character string holding a zero) otherwise true. This PMC autoconverts to an
integer or float when its integer or float value is fetched.

=item Boolean

A true/false value. Returns 0 for false, 1 for true when fetched as an
integer or float, empty string for false and '1' for true when fetched
as a string.

{{ IMPLEMENTATION NOTE: move the definitions of the Python constants
"True" and "False" out of src/pmc/boolean.pmc. They belong in
HLL-specific code, not in the core boolean type. }}

=item BigInt

An arbitrary precision integer.

=item BigNum

The PMC wrapper for Parrot's low-level BigNum type.
{{ NOTE: this type doesn't seem to exist. }}

=item Complex

A complex number, consisting of a real part and an imaginary part.
{{ NOTE: is this a complete and useful implementation of complex
numbers? }}

=item ParrotClass

The PMC for Parrot's class. (Note that this may go away if we ultimately make
all classes just objects)

=item ParrotObject

The PMC for Parrot's base object type.

=item Ref

The PMC that represents a reference to another PMC. Delegates all functions to
the referred-to PMC.

=item AggregateElementRef

This PMC represents a reference to an element contained in an aggregate PMC
type, such as an array or hash. It is initialized with the key being 
referenced and the aggregate PMC containing that key. 

Note that assigning to the reference PMC will be equivalent to a keyed set on
the referenced aggregate PMC - that is, it modifies the element rather than
doing a v-table call on the element itself. It is important to be aware of
this when assigning a PMC through this reference; it is not the same behaviour
as the Ref PMC.

=item WeakRegisterRef

This PMC represents a weak reference to a register. Should the reference live
beyond the context containing the register that it references, any attempt to
use the reference will throw an exception.

A weak register reference can only be created by the C<register_ref> opcode.
Any assignment to the register will behave like a set instruction. That is,
when assigning a PMC using a WeakRegisterRef PMC, the register will be updated
to reference that PMC rather than calling the assign v-table call on the PMC
in that register. This is not the same behaviour as the Ref PMC.

=item Random

A singleton PMC that generates a random number. {{ NOTE: Why do we have
this? }}

=back

=head3 Array types

Note that for the following types you can set the size of the array by using
the VTABLE_set_integer_native() method. Assigning an integer to the array as a
whole sets the array to that size.

Size-changing operations (such as push, pop, shift, unshift, and splice)
on statically-sized arrays will throw an exception.

=over 4

=item Array

The base class for all array types (a statically sized array for any
arbitrary type). New array types can be derived from the base Array.
In user code it is recommended to use one of the specific array types
below, rather than the base type. 

=item FixedBooleanArray

A statically sized array which holds only Boolean values.

=item ResizableBooleanArray

A dynamically sized array which holds only Boolean values.

=item FixedIntegerArray

A statically sized array which holds only Integer values.

=item ResizableIntegerArray

A dynamically sized array which holds only Integer values.

=item FixedFloatArray

A statically sized array which holds only Float values.

=item ResizableFloatArray

A dynamically sized array which holds only Float values.

=item FixedPMCArray

A statically sized array which holds only PMC values.

=item ResizablePMCArray

A dynamically sized array which holds only PMC values.

=item FixedStringArray

A statically sized array which holds only String values.

=item ResizableStringArray

A dynamically sized array which holds only String values.

=item Exception

=back

=head3 Hash types

=over 4

=item Hash

A container with key-value semantics. The values are PMCs.

=item Env

Env is a singleton PMC class, that is there is only one Env PMC in any
interpreter. This PMC gives access to the process' environment
variables--reading from it returns the value of the named process environment
variable, while writing to it sets the value of a process environment variable.
For example, to retrieve the current value of TERM (the terminal type on most
Unix systems):

   new P1, 'Env'
   set S1, P1['TERM']

Note that an embedding system may override this behavior.

=item Namespace

=item OrderedHash

=item AddrRegistry

Simulates reference counting for dead-object detection and garbage
collection.

=back

=head3 Subroutine types

=over 4

=item Sub

=item Closure

A closure: subroutine object plus captured lexical scope.

=item Coroutine

=item Continuation

=item CSub

=item Eval

=item Exception_Handler

=item MultiSub

=item NCI

A native call interface wrapper around a C function.

=item Bound_NCI

An internal NCI method call bound to a particular call instance. 
{{ NOTE: where are these used? }}

=item Compiler

A subroutine implementing a language compiler. (Derived from NCI.)

=back

=head1 ATTACHMENTS

None.

=head1 FOOTNOTES

None.

=head1 REFERENCES

None.

=cut

__END__
Local Variables:
  fill-column:78
End:<commit_msg>[pdd] Answering a round of questions for the PMC PDD, filling in details on declaring PMCs, inheritance, and composition.<commit_after># Copyright (C) 2001-2007, The Perl Foundation.
# $Id$

=head1 NAME

docs/pdds/pdd17_pmc.pod - Parrot Magic Cookies

=head1 VERSION

$Revision$

=head1 ABSTRACT

This PDD describes the internal structure and behavior of the Parrot Magic
Cookie (PMC) data type. 

=head1 DESCRIPTION

PMCs implement all internal data types more complex than a simple integer,
float, or string, and also the data types of high-level languages.  Nothing
outside the core of Parrot (in fact, nothing outside the data type's vtable
routines) should infer anything about a PMC (hence the Magic part).

This does mean, though, that you need to either know what functions are
available and what they do, or have some method of finding out. Parrot defines
a standard set of functions that each PMC provides. More complex features are
constructed out of these fundamental building blocks.

=head1 DESCRIPTION

=over 4

=item - PMCs contain both state and behavior

=item - PMCs can inherit from other PMCs

=item - PMCs can be composed of low-level roles

=item - High-level objects can subclass low-level PMCs


=back

=head1 IMPLEMENTATION

=head2 Internal structure

All PMCs have the form:

    struct PMC {
        UnionVal cache;
        Parrot_UInt flags;
        VTABLE *vtable;
        PMC *real_self;
        DPOINTER *data;
        struct PMC_EXT *pmc_ext;
    };

where C<cache> is a pointer to a C<UnionVal> union:

    typedef union UnionVal {
        struct {
            void * _bufstart;
            size_t _buflen;
        } _b;
        struct {
            DPOINTER* _struct_val;
            PMC* _pmc_val;
        } _ptrs;
        INTVAL _int_val;
        FLOATVAL _num_val;
        struct parrot_string_t * _string_val;
    } UnionVal;

C<u> holds data associated with the PMC. This can be in the form of an integer
value, a floating-point value, a string value, or a pointer to other data.
C<u> may be empty, since the PMC structure also provides a more general data
pointer, but is useful for PMCs which hold only a single piece of data (e.g.
C<PerlInts>).

C<flags> holds a set of flags associated with the PMC; these are documented  in
F<include/parrot/pobj.h>, and are generally only used within the Parrot 
internals.

C<vtable> holds a pointer to the B<vtable> associated with the PMC. This points
to a set of functions, with interfaces described in
L<Vtable Functions> that implement the basic behaviour of the PMC
(i.e. how it behaves under addition, subtraction, cloning etc.)

{{ PROPOSED:
C<real_self> holds a pointer to the PMC that dynamically dispatched method
calls should be made on. Normally this will be a pointer directly back to the
PMC itself. However, in the case that the PMC has been subclassed by a non-PMC
it will hold a pointer to the real object. This is so DYNSELF.method() style
calls will dispatch correctly, calling any methods and/or v-table methods that
have been overridden in PIR.

AR: Problem is, not all low-level PMCs have a PMCProxy that could be stored in
real_self to handle these method calls (they're only created when the subclass
is created). So, rather than storing real_self for all PMCs, we should only
store the delegator for objects that are delegated to (whether they're proxied
or otherwise delegated).

AR: Alternatively, this magic could all live in the PMCProxy: look up the
method object, and then invoke it passing in the delegator as the invocant.
(Not practical, because the code from the delegated class will expect to be
poking into the internals of the object, but will have the wrong object.)
Alternatively, we could say that PMCProxies must create PDD15 style storage for
the delegated class. (Not practical, because the delegated class methods will
expect to be poking into the internals of the object, but will have the wrong
object.)

}}

C<data> (if present) holds a pointer to any additional data associated  with
the PMC. This may be NULL.

C<pmc_ext> points to an extended PMC structure. This has the form:

    struct PMC_EXT {
        PMC *_metadata;
        struct _Sync *_synchronize; # [Note: may be deprecated, see STM]
        PMC *_next_for_GC;
    };

C<data> is a generic data pointer, as described above.

C<_metadata> holds internal PMC metadata. The specification for this has not
yet been finalized.

C<_synchronize> is for access synchronization between shared PMCs.

C<_next_for_GC> determines the next PMC in the 'used' list during dead object 
detection in the GC.

PMCs are not required to have a C<PMC_EXT> structure (i.e. C<pmc_ext> can be
null).

PMCs are used to implement the basic data types of the high level languages
running on top of Parrot. For instance, a Perl 5 C<SV> will map onto one (or
more) types of PMC, while particular Python datatypes will map onto different
types of PMC.

=head2 Defining PMCs

PMCs are declared by the C<pmclass> keyword:

  pmclass <name> <modifiers> {
  }

The modifiers specify core features such as:

=over 4

=item need_ext

Adds the C<PMC_EXT> structure when instantiating the PMC.

=item abstract

The PMC cannot be instantiated. (By convention, abstract classes are given
lower-case names.)

=item noinit

Don't generate class initialization code (don't set up a vtable for the PMC).
Used with C<abstract>.

=item dynpmc

The PMC is a dynamic PMC, so generate special class initialization code
suitable for dynamic loading at runtime.

=item singleton

The PMC is a singleton, created in the constant PMC pool.

=item no_ro

Don't create a second read-only vtable for the PMC. (Used, for example,
by STMs C<share_ro()>.)

=item is_shared

The PMC is shared (across threads).

=item extends

Inherit from another PMC. Takes one argument, the name of the PMC to inherit
from.

=item does

Compose a role. Takes one argument, the name of the role to compose. [NOTE:
this modifier has been taken from the older feature C<does> which is now called
C<provides> (fulfills|supplies|satisfies).]

=item provides

The PMC satisfies a particular low-level interface, which gives some assurances
on how and where a PMC can be used.

=over 4

=item * C<array> is an aggregate PMC with numerically-keyed elements

=item * C<hash> is an aggregate PMC with string-keyed elements

=item * C<library> corresponds to a dynamic library

=item * C<ref> references another PMC

=item * C<string> behaves similarly to the base string type

=item * C<integer> behaves similarly to the base int type

=item * C<float> behaves similarly to the base number type

=item * C<boolean> does true/false only.

=item * C<scalar> (only used by the sample src/dynpmc/foo.pmc)

=item * C<event> can be used with event queue

=back

=item hll

Declare the PMC in an HLL namespace other than the default HLL 'parrot'.
Takes one argument, the name of the HLL.

=item maps

Map the current PMC to a core PMC type for code declared in a particular
HLL. May only be used together with the C<hll> modifier.

=back

=head3 Defining attributes

The attributes of a PMC (both public and private) live in a custom
struct for the PMC, stored in the C<data> member of the C<PMC> struct.
The standard way of declaring attributes is with C<ATTR> within the body
of a C<pmclass> or C<prole> declaration.

  ATTR <type> <name> [:<modifier>];

This declaration is used to generate the data struct for the PMC
(named "Parrot_<pmcname>_Data"), including any attributes declared in a
composed role.

It's also possible to define and store the PMC's data struct manually,
but the standard declaration syntax must be used in roles, in PMCs that
compose roles, and in PMCs that will be subclassed by high-level
classes.

=head3 Defining vtable functions

Vtable functions are defined as C functions within the body of the C<pmclass>
declaration.

  STRING *get_string() {...}
  void set_string_native(STRING *value) {...}

{{ PROPOSAL: I'd like to require that all vtable functions be declared
with "VTABLE" at the beginning of the declaration, similar to "METHOD"
and "PCCMETHOD". At the very least it's self-documentation. It might
also be a useful hook for future pmc2c preprocessing. }}

Within the body of vtable functions, several shortcuts are provided:

=over 4

=item INTERP

The current interpreter object.

=item SELF

The current static invocant.

=item DYNSELF

The current dynamic invocant. [NOTE: it seems that this is actually what
most people mean when they say C<SELF>.]

=item SUPER

Calls the current method in the nearest superclass, using the static
type of C<SELF>. [NOTE: again, seems that this should be the dynamic
type, not static type.]

=item DYNSUPER

Calls the current method in the nearest superclass, using the dynamic
type of C<SELF>.

=back

=head3 Methods

Methods are declared in the body of the C<pmclass> or C<prole>
declaration with C<PCCMETHOD>.

  PCCMETHOD inspect(STRING *what :optional, int got_what :opt_flag) {...}

[NOTE: There is also an older C<METHOD> keyword, which is deprecated.]

=head2 PMCs and Namespaces

Like high-level classes, low-level PMCs are tied to a corresponding
namespace. By default this is a namespace with the same name as the PMC
in the 'parrot' HLL, but the C<hll> modifier in the C<pmclass>
declaration selects a different HLL.

Accessing a core PMC type from within an HLL other than 'parrot'
requires the same steps as accessing a class from another HLL, first
retrieving the namespace object, and then instantiating from that
namespace.

  $P0 = get_root_namespace ['parrot'; 'Integer']
  $P1 = new $P0

HLLs can choose to provide direct access to Parrot's core PMC types by
aliasing them within the HLL namespace.

=head2 Inheritance

PMCs can inherit behavior and state from other PMCs. Inheritance is performed
in the C<pmclass> declaration using the C<extends> keyword.

  pmclass Foo extends Bar {
  }

=head2 Composition

Composition is another form of code reuse in PMCs. Unlike inheritance, composed
roles aren't complete stand-alone PMCs, they are just bundles of behavior and
state that can be used within the composing PMC. As such, roles are never
instantiated directly, and are never translated to C directly. They have no
core structs, though they define attributes to be added to the PMC they are
composed into. 

When a PMC that uses a role is translated to C, the role provides vtable
functions, methods, and attributes that will be added to the generated C code
for that PMC. Composed vtable functions, methods, and attributes may not have
the same name as corresponding features defined in the composing PMC. This is
called a conflict, and must be explicitly resolved in the composing PMC. When
composed features have the same name as inherited vtable functions, methods, or
attributes, the composed feature overrides the inherited feature, just as it
would if defined in the composing PMC.

Roles are defined using the C<prole> keyword. 

  prole <name> <modifiers> {
  }

Roles can compose other roles, but they can't inherit.

Role attributes are defined using the same format as PMC attributes.

Core roles live in src/pmc along with the core PMCs, but they have a file
extension of C<.pr>.

Roles are composed into a PMC with the C<does> modifier.

=head2 Interaction between PMCs and high-level objects

High-level objects, as specified in PDD15, need to be able to inherit from
PMCs. This is achieved through the combination of a C<PMCProxy> PMC and
delegation.

For PDD15 objects, there is a corresponding instance of the C<Class> PMC. For
a PMC, however, the class definition is written in C and compiled away. There
needs to be something that can be placed in the parents list for a PDD15
class. That something is the C<PMCProxy> PMC. Like a PDD15 class, it is
stored as the C<class> element in the namespace associated with a PMC, provides
introspection facilities and can sit in an inheritance hierarchy.

The PMCProxy PMCs are only created when needed for subclassing a low-level
PMC, to avoid a large load of unused PMCProxy objects. When created, they are
cached in the class slot of the namespace corresponding to the low-level PMC,
so they are only created once.

Therefore, subclassing a PMC looks, at a PIR level, like subclassing a high
level class.

  $P0 = get_class 'Hash'
  $P1 = newclass 'MyClass'
  addparent $P1, $P0     # The new class inherits from the Hash PMC

Or, more briefly:

  $P1 = subclass 'Hash', 'MyClass'

PMCs store state in a very different way to PDD15 objects. When a method
inherited from a PMC is called on a PDD15 object, that method needs to get
a chunk of state that it can use as it wishes. Further to this, if multiple
PMCs are inherited from, they may use the state in different ways. Users of
Parrot at a PIR level should not have to care about such issues.

(AR: I'm willing to make some changes in how low-level PMCs store state in
order to make this easier.)

Therefore, when a PDD15 object is instantiated and it inherits from PMCs, an
instance of each of the PMCs that it inherits from is also created. These are
stored at the end of the object's attributes store.

When a method is called on an object whose class has PMC parents, the call is
delegated up to each of the PMC parents, in MRO order. The invocant must be
the appropriate PMC instance from the object's attribute store. For v-table
calls, this is just a case of passing the correct thing. For other methods
that are located by C<find_method>, a C<Bound_NCI> PMC is used to ensure that
the method from the PMC is invoked with the correct instance, so it has access
to the correct state.

(AR: Why isn't it called directly on the delegated PMC stored in the delegating
object's data store?)

When a PMC calls a method on itself, it may have been overridden in a high
level class. Therefore dynamic dispatches of method calls need to be done with
the vtable of the high level class, not the vtable of the PMC itself.

For PMCs that are instantiated and not overridden, the C<real_self> pointer in
the PMC structure is a reference to the PMC instance itself. If, however, it
is just acting to provide the state a PMC needs but is not the real instance,
this pointer will point to the instance of the high level class (an instance
of the C<Object> PMC). Method dispatches using C<DYNSELF> will always go
through this mechanism.

(AR: See comment above about delegated calls. Better to have the delegator
object only exist for delegated PMCs, and have DYNSELF check for it.)

Attribute access is, like method access, delegated upwards. Since attribute
lookup is a vtable method, the down case is covered by the previous paragraph.

(AR: What about overriding a low-level attribute with a high-level attribute?
Can you override the core data store of a Hash? The core struct members of an
STMLog? This would be a lot easier if low-level PMCs had a standard way of
defining their attributes (core struct members), which could be used to
generate struct declarations, to automatically fill a PMC's C<inspect>,
C<get_attr>, and C<set_attr> vtable functions, to annotate PMCProxy objects,
and to allow state for compile-time roles to be generated in the same struct as
state from the PMC itself.)

}}

If a low-level PMC expects to be overridden by high-level classes (which means
all the core low-level PMC types), it must respect a standard interface. It
must implement the C<get_attr> and C<set_attr> vtable entries for any core
attributes it expects to be accessible to subclasses.

Subclassing a low-level class from a high-level class makes an entry in the
high-level class's list of parents. This entry is a proxy class object for the
low-level PMC class that provides access to the low-level PMC's vtable
(including the implementations of get_attr and set_attr), and defines the
storage that the low-level object will need within the high-level object (this
could be as simple as a single integer attribute that gives an index into the
object's data store where an instance of the low-level class is stored).


=head1 REFERENCE

=head2 Vtable Functions

Vtables decouple the interface and implementation of various object functions. 
The actual vtable structure contains pointers to functions that implement the
methods for that particular PMC.  All pointers must point to valid functions
with appropriate prototypes.

In C code, the first parameter to any vtable routine is the current
interpreter. The second parameter is the PMC itself.

The following list details each of the vtable methods, their prototypes, and
their behavior.

=head3 Core Vtable Functions

=over 4

=item init

  void init(INTERP, PMC* self)

Called when a PMC is first instantiated. It takes an unused PMC parameter and
turns it into a PMC of the appropriate class.

=item init_pmc

  void init_pmc(INTERP, PMC* self, PMC* initializer)

Alternative entry point called when a PMC is first instantiated.  Accepts a PMC
parameter used to initialize the given object.  Interpretation of the PMC
initializer is left open, each PMC is free to choose its own implemention. A
NULL value passed as the initializer parameter is allowed.

NOTE: It is strongly suggested that init_pmc(PMCNULL) be equivalent to
init(), though there will of necessity be exceptions.

=item morph

  void morph(INTERP, PMC* self, INTVAL type)

Turn the PMC into a PMC of type I<type>. If the morphing can't be done in any
reasonable way -- for instance if an integer is asked to turn into an Array --
then the PMC is first destroyed, then recreated as an empty PMC of the new
type.

This method is primarily used when the interpreter has need of coercing a PMC
to a particular type, and isn't meant as a general purpose casting tool.
Compilers should only emit valid morphing operations.

=item mark

  void mark(INTERP, PMC* self)

Called when the DOD is tracing live PMCs. If this method is called then the
code must mark all strings and PMCs that it contains as live, otherwise they
may be collected.

This method is only called if the DOD has detected that this PMC is both alive
and has a custom mark routine as indicated by the custom mark PMC flag.  (Most
normal PMCs don't need a custom mark routine.)

If a PMC has this flag set, then it is responsible for marking all buffers and
PMCs under its control as alive. If it does not, those PMCs or buffers may be
collected later. This method does I<not> have to call the C<mark> method on any
PMCs it marks--the DOD system takes care of that. (So no need to recurse into
aggregate PMCs or anything of the sort).

This method may allocate no memory from Parrot, nor may it alter Parrot's
internal structures. It should have no side-effects from the C level either.
This routine may not throw an exception.

=item destroy

  void destroy(INTERP, PMC* self)

Called when the PMC is destroyed. This method is called by the DOD when it
determines that a PMC is dead and that the PMC has marked itself as having a
destroy method (an active finalizer).

When this method finishes, the PMC will be marked as dead. As such you should
make sure that you don't leave any references to it in any Parrot structure
by the end of the method.

This method may not throw an exception. It will be ignored if it does.

=item clone

  PMC* clone(INTERP, PMC* self)

Return a clone of a PMC.

=item defined

  INTVAL defined(INTERP, PMC* self)

Return a true value if the PMC is defined, false otherwise.

=back

=head3 Accessors

=over 4

=item getprop

  PMC* getprop(INTERP, PMC* self, STRING* key)

Return the value from the property hash of I<self> keyed by I<key>. The key
should not be NULL.

=item setprop

  void setprop(INTERP, PMC* self, STRING* key, PMC* value)

Set the value in the property hash of I<self> that is keyed by I<key> to the
value of I<value>. The key should not be NULL.

=item delprop

  void delprop(INTERP, PMC* self, STRING* key)

Delete the value from the property hash of I<self> keyed by I<key>. The key
should not be NULL.

=item getprops

  PMC* getprops(INTERP, PMC* self)

Return the entire property hash for I<self>.

=item type

  INTVAL type(INTERP, PMC* self)

Return the type of the PMC. Type is a unique number associated with the PMC when
the PMC's class is loaded. Negative numbers are considered
interpreter-specific, non-public types. [NOTE: will be deprecated when type IDs
are deprecated.]

=item subtype

  UINTVAL subtype(INTERP, PMC* self, INTVAL type) [deprecated]

Return the subtype of a PMC. (Note that this may be unimplemented, and may go
away). This is intended to return information about the PMC--what type of
number or string it is, whether it's a scalar, hash, array, or list, and
suchlike things.

[This can be adequately handled by C<does> and C<inspect>.]

=item name

  STRING* name(INTERP, PMC* self)

Return the name of the class for the PMC.

=item get_integer

  INTVAL get_integer(INTERP, PMC* self)

Return the native integer value of the PMC.

=item get_number

  FLOATVAL get_number(INTERP, PMC* self)

Return the native floating-point value of the PMC.

=item get_bignum

  PMC* get_bignum(INTERP, PMC* self)

Return the extended precision numeric value of the PMC as a new bignum PMC.

=item get_string

  STRING* get_string(INTERP, PMC* self)

Return the native string value of the PMC. This may be in any encoding, chosen
by the PMC.

=item get_bool

  INTVAL get_bool(INTERP, PMC* self)

Return the true/false value of the PMC (the constant TRUE or the constant
FALSE). The definition of truth for a given PMC will depend on the type of the
PMC. For a scalar, it may be as simple as returning false when the PMC has a
value 0 or "", and returning true when the PMC has any other value.

=item get_pmc

  PMC* get_pmc(INTERP, PMC* self)

Return the PMC value for this PMC. This is useful in circumstances where the
thing being accessed may return something other than its own value. For
example, an array might return a reference to itself. Any PMC may return a
value different from the PMC that C<get_pmc> is being called on.

=item set_integer_native

  void set_integer_native(INTERP, PMC* self, INTVAL value)

Set the integer value of this PMC from a native integer value (integer
register/constant).

=item set_integer_same

  void set_integer_same(INTERP, PMC* self, PMC* value)

Set the value of this PMC from the integer value of another PMC. The value PMC
is guaranteed to be of the same type as the I<self> PMC, so optimizations may
be made.

=item set_number_native

  void set_number_native(INTERP, PMC* self, FLOATVAL value)

Set the value of this PMC from a native floating-point value (float
register/constant).

=item set_number_same

  void set_number_same(INTERP, PMC* self, PMC* value)

Set the value of this PMC from the floating-point value another PMC. The value
PMC is guaranteed to be of the same type as the I<self> PMC, so optimizations
may be made.

=item get_pointer

  void* get_pointer(INTERP, PMC* self)

Returns a pointer value for the PMC. Useful for PMCs that hold pointers to
arbitrary data. The details of the data (type, location etc.) depend on the
PMC.

=item set_bignum_int

  void set_bignum_int(INTERP, PMC* self, INTVAL value)

Morph the PMC to a BIGNUM PMC, and set the extended-precision value from a
native integer.

=item set_string_native

  void set_string_native(INTERP, PMC* self, STRING* value)

Set the value of this PMC from a native string value (string
register/constant).

=item assign_string_native

  void assign_string_native(INTERP, PMC* self, STRING* value)

Set the value of this PMC to a copied native string value (string
register/constant).

=item set_string_same

  void set_string_same(INTERP, PMC* self, PMC* value)

Set the value of this PMC from the string value of another PMC. The value PMC
is guaranteed to be of the same type as the I<self> PMC, so optimizations may
be made.

=item set_bool

  void set_bool(INTERP, PMC* self, INTVAL value)

Set the boolean state of the PMC to TRUE if the native integer value passed in
is TRUE, or FALSE if the value is FALSE. The definition of truth is left open
to the particular PMC. For a scalar, it may be as simple as setting false when
a 0 value is passed in, and seting true when any other value is passed in.

=item assign_pmc

  void assign_pmc(INTERP, PMC* self, PMC* value)

Set the value of the PMC in I<self> to the value of the PMC in I<value> by
copying the value.

=item set_pmc

  void set_pmc(INTERP, PMC* self, PMC* value)

Make the PMC in I<self> refer to the PMC passed as I<value>.

=item set_pointer

  void set_pointer(INTERP, PMC* self, void* value)

Set the pointer value of the PMC Useful for PMCs that hold pointers to
arbitrary data. The details of the data (type, location etc.) depend on the
PMC.

=back

=head3 Aggregate Vtable Functions

Many of the following functions have a *_keyed form, a *_keyed_int form, and a
*_keyed_str form. The keyed forms take a PMC*, INTVAL, or STRING* key as a
parameter. The PMC* parameter is NULL if there is no key for that
PMC; this means that that argument is unkeyed.

In some cases, the caller must provide a non-NULL key.  Those cases are
explicitly stated below.  In the other cases, you may have to implement the
keyed vtable functions and check for a NULL I<self> key even if you are
implementing a non-aggregate type.  If the I<self> key is non-NULL and the PMC
class is a non-aggregate type, the _keyed_* methods should throw an exception.

If you do not implement the *_keyed_int and *_keyed_str functions, the default
will convert the INTVAL or STRING* into a key PMC* and call the corresponding
*_keyed functions.

=over 4

=item elements

  INTVAL elements(INTERP, PMC* self)

Return the number of elements in the PMC.

=item get_integer_keyed

  INTVAL get_integer_keyed(INTERP, PMC* self, PMC* key)

Return the integer value for the element indexed by a PMC key.  The key is
guaranteed not to be NULL for this function.

=item get_integer_keyed_int

  INTVAL get_integer_keyed_int(INTERP, PMC* self, INTVAL key)

Return the integer value for the element indexed by an integer key.  The key is
guaranteed not to be NULL for this function.

=item get_integer_keyed_str

  INTVAL get_integer_keyed_str(INTERP, PMC* self, STRING* key)

Return the integer value for the element indexed by a string key.  The key is
guaranteed not to be NULL for this function.

=item get_number_keyed

  FLOATVAL get_number_keyed(INTERP, PMC* self, PMC* key)

Return the native floating-point value for the element indexed by a PMC key.
The key is guaranteed not to be NULL for this function.

=item get_number_keyed_int

  FLOATVAL get_number_keyed_int(INTERP, PMC* self, INTVAL key)

Return the native floating-point value for the element indexed by an integer
key. The key is guaranteed not to be NULL for this function.

=item get_number_keyed_str

Return the native floating-point value for the element indexed by a string key.
The key is guaranteed not to be NULL for this function.

=item get_string_keyed

  STRING* get_string_keyed(INTERP, PMC* self, PMC* key)

Return the string value for the element indexed by a PMC key.
The key is guaranteed not to be NULL for this function.

=item get_string_keyed_int

  STRING* get_string_keyed_int(INTERP, PMC* self, INTVAL key)

Return the string value for the element indexed by an integer key.
The key is guaranteed not to be NULL for this function.

=item get_string_keyed_str

  STRING* get_string_keyed_str(INTERP, PMC* self, STRING* key)

Return the string value for the element indexed by a string key.
The key is guaranteed not to be NULL for this function.

=item get_bool_keyed

Return the boolean value for the element indexed by a PMC key.

=item get_bool_keyed_int

Return the boolean value for the element indexed by an integer key.

=item get_bool_keyed_str

Return the boolean value for the element indexed by a string key.

=item get_pmc_keyed

  PMC* get_pmc_keyed(INTERP, PMC* self, PMC* key)

Return the PMC value for the element indexed by a PMC key.
The key is guaranteed not to be NULL for this function.

=item get_pmc_keyed_int

  PMC* get_pmc_keyed_int(INTERP, PMC* self, INTVAL key)

Return the PMC value for the element indexed by an integer key.
The key is guaranteed not to be NULL for this function.

=item get_pmc_keyed_str

  PMC* get_pmc_keyed_str(INTERP, PMC* self, STRING* key)

Return the PMC value for the element indexed by a string key.
The key is guaranteed not to be NULL for this function.

=item get_pointer_keyed

  void* get_pointer_keyed(INTERP, PMC* self, PMC* key)

Return the pointer value for the element indexed by a PMC key. The details of
the data (type, location etc.) depend on the PMC.

=item get_pointer_keyed_int

  void* get_pointer_keyed_int(INTERP, PMC* self, INTVAL key)

Return the pointer value for the element indexed by an integer key. The
details of the data (type, location etc.) depend on the PMC.

=item get_pointer_keyed_str

  void* get_pointer_keyed_str(INTERP, PMC* self, STRING* key)

Return the pointer value for the element indexed by a string key. The details
of the data (type, location etc.) depend on the PMC.

=item set_integer_keyed

  void set_integer_keyed(INTERP, PMC* self, PMC* key, INTVAL value)

Set the integer value of the element indexed by a PMC key. The key is
guaranteed not to be NULL for this function.

=item set_integer_keyed_int

  void set_integer_keyed_int(INTERP, PMC* self, INTVAL key, INTVAL value)

Set the integer value of the element indexed by an integer key. The key is
guaranteed not to be NULL for this function.

=item set_integer_keyed_str

  void set_integer_keyed_str(INTERP, PMC* self, STRING* key, INTVAL value)

Set the integer value of the element indexed by a string key. The key is
guaranteed not to be NULL for this function.

=item set_number_keyed

  void set_number_keyed(INTERP, PMC* self, PMC* key, FLOATVAL value)

Set the floating-point value of the element indexed by a PMC key. The key is
guaranteed not to be NULL for this function.

=item set_number_keyed_int

  void set_number_keyed_int(INTERP, PMC* self, INTVAL key, FLOATVAL value)

Set the floating-point value of the element indexed by an integer key. The key
is guaranteed not to be NULL for this function.

=item set_number_keyed_str

  void set_number_keyed_str(INTERP, PMC* self, STRING* key, FLOATVAL value)

Set the floating-point value of the element indexed by a string key. The key
is guaranteed not to be NULL for this function.

=item set_string_keyed

  void set_string_keyed(INTERP, PMC* self, PMC* key, STRING* value)

Set the string value of the element indexed by a PMC key.  The key is
guaranteed not to be NULL for this function.

=item set_string_keyed_int

  void set_string_keyed_int(INTERP, PMC* self, INTVAL key, STRING* value)

Set the string value of the element indexed by an integer key.  The key is
guaranteed not to be NULL for this function.

=item set_string_keyed_str

  void set_string_keyed_str(INTERP, PMC* self, STRING* key, STRING* value)

Set the string value of the element indexed by a string key.  The key is
guaranteed not to be NULL for this function.

=item set_pmc_keyed

  void set_pmc_keyed(INTERP, PMC* self, PMC* key, PMC* value)

Set the value of the element indexed by a PMC key, by copying the value of
another PMC.

=item set_pmc_keyed_int

  void set_pmc_keyed_int(INTERP, PMC* self, INTVAL key, PMC* value)

Set the PMC value of the element indexed by an integer key, by copying the
value of another PMC.

=item set_pmc_keyed_str

  void set_pmc_keyed_str(INTERP, PMC* self, STRING* key, PMC* value)

Set the PMC value of the element indexed by a string key, by copying the value
of another PMC.

=item set_pointer_keyed

  void set_pointer_keyed(INTERP, PMC* self, PMC* key, void* value)

Set the pointer value of the element indexed by a PMC key.

=item set_pointer_keyed_int

  void set_pointer_keyed_int(INTERP, PMC* self, INTVAL key, void* value)

Set the pointer value of the element indexed by an integer key.

=item set_pointer_keyed_str

  void set_pointer_keyed_str(INTERP, PMC* self, STRING* key, void* value)

Set the pointer value of the element indexed by a string key.

=item type_keyed

  INTVAL type_keyed(INTERP, PMC* self, PMC* key)

Return the type number of the PMC indexed by a PMC key.  The I<key> parameter
is guaranteed not to be NULL for this method. [NOTE: To be deprecated when type
IDs are deprecated.]

=item type_keyed_int

  INTVAL type_keyed_int(INTERP, PMC* self, INTVAL key)

Return the type number of the PMC indexed by an integer key.  The I<key>
parameter is guaranteed not to be NULL for this method. [NOTE: To be deprecated
when type IDs are deprecated.]

=item type_keyed_str

  INTVAL type_keyed_str(INTERP, PMC* self, STRING* key)

Return the type number of the PMC indexed by a string key.  The I<key>
parameter is guaranteed not to be NULL for this method. [NOTE: To be deprecated
when type IDs are deprecated.]

=item pop_integer

  INTVAL pop_integer(INTERP, PMC* self)

Return the integer value of the last item on the list, removing that item.

=item pop_float

  FLOATVAL pop_float(INTERP, PMC* self)

Return the floating-point value of the last item on the list, removing that
item.

=item pop_string

  STRING* pop_string(INTERP, PMC* self)

Return the string value of the last item on the list, removing that item.

=item pop_pmc

  PMC* pop_pmc(INTERP, PMC* self)

Return the PMC value of the last item on the list, removing that item.

=item push_integer

  void push_integer(INTERP, PMC* self, INTVAL value)

Add the passed in integer value to the end of the list.

=item push_float

  void push_float(INTERP, PMC* self, FLOATVAL value)

Add the passed in floating-point number to the end of the list.

=item push_string

  void push_string(INTERP, PMC* self, STRING* value)

Add the passed in string to the end of the list.

=item push_pmc

  void push_pmc(INTERP, PMC* self, PMC* value)

Add the passed in PMC to the end of the list.

=item shift_integer

  INTVAL shift_integer(INTERP, PMC* self)

Return the integer value of the first item on the list, removing that item.

=item shift_float

  FLOATVAL shift_float(INTERP, PMC* self)

Return the floating-point value of the first item on the list, removing that
item.

=item shift_string

  STRING* shift_string(INTERP, PMC* self)

Return the string value of the first item on the list, removing that item.

=item shift_pmc

  PMC* shift_pmc(INTERP, PMC* self)

Return the PMC value of the first item on the list, removing that item.

=item unshift_integer

  void unshift_integer(INTERP, PMC* self, INTVAL value)

Add the passed in integer value to the beginning of the list.

=item unshift_float

  void unshift_float(INTERP, PMC* self, FLOATVAL value)

Add the passed in floating-point number to the beginning of the list.

=item unshift_string

  void unshift_string(INTERP, PMC* self, STRING* value)

Add the passed in string to the beginning of the list.

=item unshift_pmc

  void unshift_pmc(INTERP, PMC* self, PMC* value)

Add the passed in PMC to the beginning of the list.

=item splice

  void splice(INTERP, PMC* self, PMC* value, INTVAL offset, INTVAL count)

Replace the I<count> PMCs at offset I<offset> from the beginning of I<self>
with the PMCs in the aggregate I<value>.

=item exists_keyed

=item exists_keyed_int

=item exists_keyed_str

=item defined_keyed

=item defined_keyed_int

=item defined_keyed_str

=item dtem delete_keyed_str

=item nextkey_keyed

=item nextkey_keyed_itr_str

=back

=head3 Math Vtable Functions

=over 4

=item add

  void add(INTERP, PMC* self, PMC* value, PMC* dest)
  void add_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void add_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Add the value of I<self> to the value of a PMC, native integer, or native
floating-point number and store the result in a PMC I<dest>. Note that I<dest>
may be the same PMC as I<self>; in that case optimizations may be made.

=item subtract

  PMC* subtract(INTERP, PMC* self, PMC* value, PMC* dest)
  PMC* subtract_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  PMC* subtract_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Subtract the value of a PMC, native integer, or native floating-point number
from a PMC and store the result in I<dest>. If I<dest> is NULL create a result
PMC of an appropriate type.  Note that I<dest> may be the same PMC as I<self>;
in that case optimizations may be made.

=item i_subtract

  void i_subtract(INTERP, PMC* self, PMC* value)
  void i_subtract_int(INTERP, PMC* self, INTVAL value)
  void i_subtract_float(INTERP, PMC* self, FLOATVAL value)

Inplace operation: subtract a PMC, native integer, or native floating-point
number from the value of a PMC and store the result back in the same PMC.

=item increment

=item decrement

=item multiply

  void multiply(INTERP, PMC* self, PMC* value, PMC* dest)
  void multiply_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void multiply_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Multiply a PMC, native integer, or floating-point value by the value of the PMC
I<self> and store the result in the I<dest> PMC. Note that I<dest> may be the
same PMC as I<self>; in that case optimizations may be made.

=item divide

  void divide(INTERP, PMC* self, PMC* value, PMC* dest)
  void divide_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void divide_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Divide the value of the I<self> PMC by a PMC, native integer, or native
floating-point number and store the result in I<dest>.  Note that I<dest> may
be the same PMC as I<self>; in that case optimizations may be made.

=item modulus

  void modulus(INTERP, PMC* self, PMC* value, PMC* dest)
  void modulus_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void modulus_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Divide the value of the I<self> PMC by the value of a PMC, native integer, or
native floating-point number and store the remainder in I<dest>.  Note that
I<dest> may be the same PMC as I<self>; in that case optimizations may be made.

=item cmodulus

  void cmodulus(INTERP, PMC* self, PMC* value, PMC* dest)
  void cmodulus_int(INTERP, PMC* self, INTVAL value, PMC* dest)
  void cmodulus_float(INTERP, PMC* self, FLOATVAL value, PMC* dest)

Divide the value of the I<self> PMC by the value of a PMC, native integer, or
native floating-point number and store the remainder in I<dest>.  Note that
I<dest> may be the same PMC as I<self>; in that case optimizations may be made.

Note that C<modulus> uses Knuth's "corrected mod" algorithm, as implemented in
F<src/utils.c>, while C<cmodulus> uses the C-style fmod function.

=item neg

  void neg(INTERP, PMC* self, PMC* dest)

Negate the sign of I<self> and store the result in I<dest>. Note that I<self>
and I<dest> may refer to the same PMC, in which case optimizations may be
made.

=back

=head3 Logical Vtable Functions

=over 4

=item bitwise_or

  void bitwise_or(INTERP, PMC* self, PMC* value, PMC* dest)
  void bitwise_or_int(INTERP, PMC* self, INTVAL value, PMC* dest)

Calculate the bitwise-OR of the value of the I<self> PMC and the value of a PMC
or native integer and store the result in I<dest>. Note that I<dest> may be the
same PMC as I<self>; in that case optimizations may be made.
[Question: what happens when the I<self> and I<value> PMCs aren't integers?]

=item bitwise_and

=item bitwise_and_int

=item bitwise_xor

=item bitwise_xor_int

=item bitwise_ors

=item bitwise_ors_str

=item bitwise_ands

=item bitwise_ands_str

=item bitwise_xors

=item bitwise_xors_str

=item bitwise_not

=item bitwise_shl

=item bitwise_shl_int

=item bitwise_shr

=item bitwise_shr_int

=item is_equal

=item is_same

=item cmp

=item cmp_num

=item cmp_string

=item logical_or

=item logical_and

=item logical_xor

=item logical_not

=back

=head3 String Vtable Functions

=over 4

=item concatenate

=item concatenate_native

=item repeat

=item repeat_int

=back

=head3 Code Vtable Functions

=over 4

=item invoke

=item fsh

=item visit

=item share

=back

=head3 Class/Object Vtable Functions

=over 4

=item can

=item does

=item isa

=item add_method

=item add_attribute

=item get_attr

=item set_attr

=item add_parent

=item add_role

=item PMC* find_method(INTERP, PMC* self, STRING* method_name)

Return a subroutine PMC for the passed method name. This subroutine PMC may be
cached, so the method I<must> return an equivalent sub PMC each time, or be
capable of dealing with the returned sub PMCs being reused. [Why should it be
cached? Can you turn off caching? What if you want to override find_method to
generate methods on the fly?]


=back



=head2 Core PMCs

Parrot has a number of core PMC types that all programs can guarantee will be
available to them. (With the possible exception of Parrot programs executing on
an embedded device or other restricted environment)

=head3 Scalar types

=over 4

=item Undef

This is the generic no-value type. It has a numeric value of zero, a string
value of empty string, and a boolean value of false. It will, on assignment,
turn itself into a PMC of the source type, or if assigned a basic type will
turn itself into one of the wrapper PMC types (detailed below) for the basic
types.

=item Integer

The PMC wrapper for Parrot's low-level integer type. Always an integer, with
other types auto-converted to an integer when stored into this PMC. The range
and behaviour of the Integer PMC is identical to the platform low-level
integer.

The boolean value for an Integer is false if zero, otherwise true.

Floating point, string, and bignum values assigned to an Integer PMC round to
the nearest integer. Floats, or strings which resolve to numbers, cap at the
platform maximum or minimum integer value.

Integer PMCs take on a value of 1 if a boolean true is assigned, and a value of
0 if a boolean false is assigned.

If an out-of-range value is assigned to an Integer PMC, the PMC will throw an
exception if exact math is enabled.

=item Float

The PMC wrapper for Parrot's low-level floating-point type. Always a float,
with other types autoconverted to a float when stored into this PMC.

The boolean value for a Float is false if exactly zero, otherwise true.

When converted to an integer, floats round to the closest integer, capping at
the platform maximum or minimum integer value.

When converting to a string, floats use the platform default snprintf format.

=item String

The PMC wrapper for Parrot's low-level string type. Always a simple string,
with other types autoconverted to a string when stored into this PMC.

The boolean value for a String is false if empty or the string '0' (a one
character string holding a zero) otherwise true. This PMC autoconverts to an
integer or float when its integer or float value is fetched.

=item Boolean

A true/false value. Returns 0 for false, 1 for true when fetched as an
integer or float, empty string for false and '1' for true when fetched
as a string.

{{ IMPLEMENTATION NOTE: move the definitions of the Python constants
"True" and "False" out of src/pmc/boolean.pmc. They belong in
HLL-specific code, not in the core boolean type. }}

=item BigInt

An arbitrary precision integer.

=item BigNum

The PMC wrapper for Parrot's low-level BigNum type.
{{ NOTE: this type doesn't seem to exist. }}

=item Complex

A complex number, consisting of a real part and an imaginary part.
{{ NOTE: is this a complete and useful implementation of complex
numbers? }}

=item ParrotClass

The PMC for Parrot's class. (Note that this may go away if we ultimately make
all classes just objects)

=item ParrotObject

The PMC for Parrot's base object type.

=item Ref

The PMC that represents a reference to another PMC. Delegates all functions to
the referred-to PMC.

=item AggregateElementRef

This PMC represents a reference to an element contained in an aggregate PMC
type, such as an array or hash. It is initialized with the key being 
referenced and the aggregate PMC containing that key. 

Note that assigning to the reference PMC will be equivalent to a keyed set on
the referenced aggregate PMC - that is, it modifies the element rather than
doing a v-table call on the element itself. It is important to be aware of
this when assigning a PMC through this reference; it is not the same behaviour
as the Ref PMC.

=item WeakRegisterRef

This PMC represents a weak reference to a register. Should the reference live
beyond the context containing the register that it references, any attempt to
use the reference will throw an exception.

A weak register reference can only be created by the C<register_ref> opcode.
Any assignment to the register will behave like a set instruction. That is,
when assigning a PMC using a WeakRegisterRef PMC, the register will be updated
to reference that PMC rather than calling the assign v-table call on the PMC
in that register. This is not the same behaviour as the Ref PMC.

=item Random

A singleton PMC that generates a random number. {{ NOTE: Why do we have
this? }}

=back

=head3 Array types

Note that for the following types you can set the size of the array by using
the VTABLE_set_integer_native() method. Assigning an integer to the array as a
whole sets the array to that size.

Size-changing operations (such as push, pop, shift, unshift, and splice)
on statically-sized arrays will throw an exception.

ResizablePMCArray returns Undef for unset elements (so does the new
object model, because it uses ResizablePMCArray for storage), but Hash
returns PMCNULL. Standardize all core aggregate PMC types on the
singleton PMCNULL.

=over 4

=item Array

The base class for all array types (a statically sized array for any
arbitrary type). New array types can be derived from the base Array.
In user code it is recommended to use one of the specific array types
below, rather than the base type. 

=item FixedBooleanArray

A statically sized array which holds only Boolean values.

=item ResizableBooleanArray

A dynamically sized array which holds only Boolean values.

=item FixedIntegerArray

A statically sized array which holds only Integer values.

=item ResizableIntegerArray

A dynamically sized array which holds only Integer values.

=item FixedFloatArray

A statically sized array which holds only Float values.

=item ResizableFloatArray

A dynamically sized array which holds only Float values.

=item FixedPMCArray

A statically sized array which holds only PMC values.

=item ResizablePMCArray

A dynamically sized array which holds only PMC values.

=item FixedStringArray

A statically sized array which holds only String values.

=item ResizableStringArray

A dynamically sized array which holds only String values.

=item Exception

=back

=head3 Hash types

=over 4

=item Hash

A container with key-value semantics. The values are PMCs.

=item Env

Env is a singleton PMC class, that is there is only one Env PMC in any
interpreter. This PMC gives access to the process' environment
variables--reading from it returns the value of the named process environment
variable, while writing to it sets the value of a process environment variable.
For example, to retrieve the current value of TERM (the terminal type on most
Unix systems):

   new P1, 'Env'
   set S1, P1['TERM']

Note that an embedding system may override this behavior.

=item Namespace

=item OrderedHash

=item AddrRegistry

Simulates reference counting for dead-object detection and garbage
collection.

=back

=head3 Subroutine types

=over 4

=item Sub

=item Closure

A closure: subroutine object plus captured lexical scope.

=item Coroutine

=item Continuation

=item CSub

=item Eval

=item Exception_Handler

=item MultiSub

=item NCI

A native call interface wrapper around a C function.

=item Bound_NCI

An internal NCI method call bound to a particular call instance. 
{{ NOTE: where are these used? }}

=item Compiler

A subroutine implementing a language compiler. (Derived from NCI.)

=back

=head1 ATTACHMENTS

None.

=head1 FOOTNOTES

None.

=head1 REFERENCES

  docs/pmc2c.pod

=cut

__END__
Local Variables:
  fill-column:78
End:
{'fraction_non_alphanumeric': 0.05147574596665408, 'fraction_numerical': 0.0021367290778611125, 'mean_word_length': 4.182662192393736, 'pattern_counts': {'":': 0, '<': 271, '<?xml version=': 0, '>': 271, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1528324', 'n_tokens_mistral': 28727, 'n_tokens_neox': 27667, 'n_words': 14472}