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)

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

Returns 0 if the method has thrown an exception.

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

Returns 0 if the method has thrown an exception.

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 routine may not throw an exception.

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

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.

Returns NULL if this throws an exception.

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.

Returns NULL if this throws an exception.

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.

Returns NULL if this throws an exception.

INTVAL get_integer(PMC)

Returns the native integer value of the PMC.

Returns 0 if this method throws an exception, at which point the current exception status must be checked to see if an exception was really thrown.

NUMVAL get_number(PMC)

Returns the native float value of the PMC.

Returns 0 if this method throws an exception, at which point the current exception status must be checked to see if an exception was actually thrown. This does not return NaN or other IEEE "interesting" constants since we're not requiring IEEE compliant floats.

BIGNUM *get_bignum(PMC)

Returns the value of the PMC as a bignum.

Returns NULL if this method throws an exception.

STRING *get_string(PMC)

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

Returns 0 if this method throws an exception.

INTVAL get_bool(PMC)

Returns the constant PARROT_TRUE (1) if the PMC is true, or PARROT_FALSE(-1) if the PMC is false.

Returns 0 if this method has thrown an exception.

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.

Returns NULL if this method throws an exception.

INTVAL is_same(PMC, PMC)

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

This method returns 0 if an exception is thrown.

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

Returns 0 if an exception is thrown.

INTVAL set_number(PMC, NUMVAL)

Sets the PMC to the numeric value passed in.

Returns 0 if an exception is thrown.

INTVAL set_bignum(PMC, BIGNUM *)

Sets the PMC to the passed in bignum value.

Returns 0 if the method throws an exception.

INTVAL set_string(PMC, STRING *)

Sets the PMC to the passed in string value.

Returns 0 if the method throws an exception.

INTVAL set_pmc(PMC, PMC)

Assigns the source PMC to the destination PMC.

Returns 0 if the method throws an exception.

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

Returns 0 if an exception is thrown.

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, returns a PMC with the result, and NULL if an exception is thrown.

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.

Returns NULL if an exception is thrown.

INTVAL is_equal(PMC, PMC)

Returns PARROT_TRUE if the two PMCs are generically equivalent, or PARROT_false if they aren't. Returns 0 on exception.

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, 2 if they are equal, and three 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.

Returns 0 if the methods throw an exception.

PMC *logical_or(PMC, PMC)

Does a short-circuiting logical or, and returns the PMC that wins. Returns NULL on exception.

PMC *logical_and(PMC, PMC)

Does a short-circuiting logical and and returns the PMC that wins. Returns NULL on exception.

PMC *logical_xor(PMC, PMC)

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

Returns NULL on exception.

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.

Returns NULL on exception.

INTVAL increment(PMC)

Autoincrement the PMC.

Returns 0 on exception.

INTVAL decrement(PMC)

Autodecrement the PMC.

Returns 0 on exception.

INTVAL exists(PMC, key)

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

Returns 0 on exception.

INTVAL defined(PMC)

Checks to see if the PMC is defined. Returns PARROT_TRUE or PARROT_FALSE, or 0 if an exception is thrown.

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, or NULL if an exception has been thrown.