TITLE

Common vtable format for all variables

VERSION

CURRENT

Maintainer: Dan Sugalski <dan@sidhe.org>
Class: Internals
PDD Number: 2
Version: 1.1
Status: Developing
Last Modified: 13 May 2002
PDD Format: 1
Language: English

HISTORY

1.1

13 May 2002

1.0

None. First version

CHANGES

1.1

Cleaned up the definition. It was a mess.

1.0

None. First version

ABSTRACT

This RFC presents the vtable entries, and their order, that all variables MUST provide.

DESCRIPTION

All perl variables hide their guts behind a magic perl structure generally referred to as a PMC, or Perl Magic Cookie. Nothing outside the core of perl (in fact, nothing outside the data type's vtable routines) should infer anything about a PMC. (hence the Magic part)

The first parameter to all of these should be the destination PMC.

vtables are neat because they decouple the interface and implementation of various object functions. 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 perl's using.

IMPLEMENTATION

vtable functions

The following functions are singleton functions. (There are no keyed versions of these)

void init(PMC)

The init vtable method takes an unused PMC as a parameter, and turns it into a PMC appropriate for the class owning the vtable. Called as a class method.

void morph(PMC, type)

turns the PMC into a PMC of type type. If the morphing can't be reasonably done, for example if an integer is asked to turn into a PerlArray, 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 transformations.

PMC mark(PMC, PMC)

Called by the DOD when its sweeping through the PMCs and has detected that this PMC is both alive and has a custom mark routine. The second parameter is the PMC at the tail of the free PMC list, as passed to mark_used. This should return the new tail of the free PMC list.

If a PMC has this set, its 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 not have to call the 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.

void destroy(PMC)

This method is called by the DOD when it determines that a PMC is dead, and that PMC has marked itself as having a destroy method.

When this method finishes, the PMC will be marked as dead. As such you should make sure that you do not 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.

The following functions have two forms, a plain form and a _keyed form. The keyed form takes a KEY for each PMC parameter.

INTVAL type(PMC)

Return the type of the PMC. Type is a unique tag associated with the PMC when the PMC's class is loaded. Negative numbers are considered interpreter-specific, non-public types.

UINTVAL subtype(PMC, type)

Returns 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.

STRING *name(PMC)

Return the name of the class for the PMC.

PMC *clone(PMC)

Return a clone of the specified PMC. If the PMC is fake, for example we're asking for a clone of an element of an integer array, this must return an appropriate real PMC that holds the fake information.

PMC *find_method(PMC, string)

Returns a subroutine PMC for the passed method name. This subroutine PMC may be cached, so the method must return an equivalent sub PMC each time, or be capable of dealing with the returned sub PMCs being reused.

INTVAL get_integer(PMC)

Returns the native integer value of the PMC.

NUMVAL get_number(PMC)

Returns the native float value of the PMC.

BIGNUM *get_bignum(PMC)

Returns the value of the PMC as a bignum.

STRING *get_string(PMC)

Returns the native string value of the PMC. This may be in the encoding of the PMC's choice.

INTVAL get_bool(PMC)

Returns the constant TRUE if the PMC is true, or FALSE if the PMC is false.

INTVAL elements(PMC)

Returns the number of elements in the PMC.

PMC *get_pmc(PMC)

Returns the PMC for this PMC. While this may seem nonsensical, it's useful in several circumstances. If the PMC is being accessed with a key, it returns the PMC for the thing being accessed. If the thing being accessed may return something odd, for example a reference, it may return a value different than the PMC that get_pmc is being called on.

INTVAL is_same(PMC, PMC)

Returns TRUE if the PMCs are the same, and FALSE if they're not. In this case, "the same" means identical at a low level. For plain equality, use the is_equal method.

void set_integer(PMC, INTVAL)

Sets the PMC to the integer value passed. What the PMC does with the passed in integer depends on the class.

void set_number(PMC, NUMVAL)

Sets the PMC to the numeric value passed in.

void set_bignum(PMC, BIGNUM *)

Sets the PMC to the passed in bignum value.

void set_string(PMC, STRING *)

Sets the PMC to the passed in string value.

void set_pmc(PMC, PMC)

Assigns the source PMC to the destination PMC.

void set_same(PMC, PMC)

A shortcut version of set_pmc in those cases where the interpreter knows the source and destination PMCs are of the same type.

The following vtable functions come in multiple flavors, one for each numeric type (INTVAL, NUMVAL, BIGNUM) and a PMC. Each flavor has a keyed and non-keyed version.

Each function does what its name implies and returns a PMC with the result.

PMC *add(PMC, value)
PMC *subtract(PMC, value)
PMC *multiply(PMC, value)
PMC *divide(PMC, value)
PMC *modulus(PMC, value)

The following vtable functions all have a keyed and non-keyed version.

PMC *concatenante(PMC, value)

There are two forms of this, where value is a STRING and where it's a PMC. In either case, a PMC representing the two source values concatenated together is returned.

INTVAL is_equal(PMC, PMC)

Returns TRUE if the two PMCs are generically equivalent, or FALSE if they aren't.

INTVAL cmp(PMC, PMC) =item INTVAL cmp_num(PMC, PMC) =item INTVAL cmp_string(PMC, PMC)

Compares the two PMCs. Returns -1 if the left PMC is smaller, 0 if they are equal, and 1 if the right PMC is smaller. cmp compares the two as PMCs (whatever that means for the class), cmp_num compares them numerically, and cmp_string compares them as strings.

PMC *logical_or(PMC, PMC)

Does a short-circuiting logical or, and returns the PMC that wins.

PMC *logical_and(PMC, PMC)

Does a short-circuiting logical and and returns the PMC that wins.

PMC *logical_xor(PMC, PMC)

Does a logical xor on the two parameters and returns a PMC representing the result.

PMC *repeat(PMC, value)

Where value can be either an INTVAL or a PMC. Returns a PMC that represents the leftmost PMC repeated value times.

void increment(PMC)

Autoincrement the PMC.

void decrement(PMC)

Autodecrement the PMC.

INTVAL exists(PMC, key)

This is only valid for keyed access. Returns TRUE or FALSE if the key exists or doesn't in the aggregate being queried.

INTVAL defined(PMC)

Checks to see if the PMC is defined. Returns TRUE or FALSE.

void delete(PMC, key)

Delete the specified entry from the aggregate.

KEY *nextkey(PMC, key)

Given the passed in key for the PMC, return the next key.

PMC *substr(PMC, offset, length) =item STRING *substr_str(PMC, offset, length)

Return a substring of the passed in PMC. Returns a substring, either as a PMC or a STRING.