Okay, here's the VTABLE PDD. Comments, please. (As if there's any worry
about not having any.... :)
-----Snip here--------------
=head1 TITLE
Common vtable format for all variables
=head1 VERSION
=head2 CURRENT
Maintainer: Dan Sugalski <[EMAIL PROTECTED]>
Class: Internals
PDD Number: 2
Version: 1
Status: Developing
Last Modified: 05 February 2001
PDD Format: 1
Language: English
=head2 HISTORY
None. First version
=head1 CHANGES
None. First version
=head1 ABSTRACT
This RFC presents the vtable entries, and their order, that all
variables MUST provide.
=head1 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.
=head1 IMPLEMENTATION
=head2 Core datatypes
For ease of use, we define the following semi-abstract data types
=over 4
=item INT
This is a generic integral value
=item NUM
This is a generic floating point value
=item STR
This is a generic string value
=item BOOL
This is a generic boolean value
=back
See the PDD specifying perl's internal data types for more details,
but in a nutshell they are:
=head3 Integer data types
=over 4
=item IV
This is a platform-native integer. Probably 32 or 64 bits, though
there's no guarantee made.
=item bigint
This is perl's big integer format. It's an infinite (more or less,
until you run out of memory) precision integer.
=back
=head3 Floating point data types
=over 4
=item NV
The platform-native floating point value. Probably around 80 bits
(with 53 bits of precision) though that will vary from system to system.
=item bigfloat
Perl's big floating point format. Again potentially infinite
precision, within the limits of available memory.
=back
=head3 String data types
All perl strings are counted, of course, so we don't have any
forbidden characters and take steps against buffer overruns reasonably
easily.
=over 4
=item binary buffer
This is a buffer of binary data. Perl makes no assumptions about its
contents, and won't ever implicitly translate it to any other representation.
=item UTF-32 string
This is a Unicode string in UTF-32 format.
=item Native string
This is a string in platform native format.
=item Foreign string
This is a string in a non-native format for the platform that perl
still knows how to deal with.
=back
=head2 vtable functions
The following functions are defined:
IV type(PMC[, subtype]);
STR name(PMC[, key]);
void new(PMC[, key]);
void clone(PMC, PMC[, flags[,key]);
void morph(PMC, type[, key]);
BOOL move_to(void *, PMC);
IV real_size(PMC[, key]);
void destroy(PMC[, key]);
INT get_integer(PMC[, key]); ##
NUM get_number(PMC[, key]); ##
STR get_string(PMC[, key]); ##
BOOL get_bool(PMC[, key]); ##
void * get_value(PMC[, key]);
BOOL is_same(PMC, PMC[, key]);
void set_integer(PMC, INT[, key]); ##
void set_number(PMC, NUM[, key]); ##
void set_string(PMC, STR[, key]); ##
void set_value(PMC, void *[, key]);
void add(PMC, PMC, PMC[, key]); ##
void subtract(PMC, PMC, PMC[, key]); ##
void multiply(PMC, PMC, PMC[, key]); ##
void divide(PMC, PMC, PMC[, key]); ##
void modulus(PMC, PMC, PMC[, key]); ##
void concatenate(PMC, PMC, PMC[, key]); ##
BOOL is_equal(PMC, PMC[,key]); ##
void logical_or(PMC, PMC, PMC[, key]); ##
void logical_and(PMC, PMC, PMC[, key]); ##
void logical_not(PMC, PMC[,key]); ##
void match(PMC, PMC, REGEX[, key]);
void repeat(PMC, PMC, PMC[, key]); ##
void nextkey(PMC, PMC, start_key[, key]);
BOOL exists(PMC[, key]);
All the functions marked with ## must have multiple forms, one for
each possible form of a data type. (IV, bigint, etc) Perl will
automatically produce conversion code if a vtable doesn't have code to
handle a particular type.
The functions are divided into two broad categories, those that perl
will use the value of internally (for example the type functions) and
those that produce or modify a PMC, such as the add function.
The internal functions are things perl uses to fetch specific pieces
of information, or meta-information, out of a PMC. They return the
appropriate value, depending on how they are called.
The functions that modify or create a PMC get passed a pointer to one
as their first argument, and don't return anything. (Return values,
while convenient, cost some CPU cycles so we don't have one. You pass
in the PMC, so it's not like one's handy, after all)
Ever function that has an input PMC as its last argument takes an
optional key structure so we don't have to completely dereference
things. (C<$a = $b + $c{foo}> becomes a single vtable function call and
therefore a single opcode, albeit one that does a bunch under the
hood...) Whether key structures will be passed for other PMCs is still
up in the air.
The C<key> parameter is optional, and if passed it refers to an array
of key structure pointers. Entry 0 in the array is the key for the
first PMC in the list, entry 1 is for the second, and so on. If a key
pointer is NULL it means that there's no key for that particular
PMC. The key structure is:
struct key {
IV key_type;
union {
struct hash_key *hash_key;
IV array_offset;
}
}
This way, the statement
$foo{bar} = $bar{baz} + $xyzzy[42];
can be expressed in a single call.
=head2 Functions in detail
=over 3
=item type
IV type(PMC[, subtype]);
Returns the type of the PMC. If the subtype is passed (int, string,
num) it returns the subtype of the PMC. This is generally a class
function rather than a variable one, but the PMC is passed in just in
case. (And so we can have the subtype be a vararg parameter)
=item name
STR name(PMC[, key]);
Returns the name of the class the PMC belongs to.
=item new
void new(PMC[, key]);
Creates a new variable of the appropriate type out of the passed PMC,
destroying the current contents if there are any. This is a class
function.
=item clone
void clone(PMC1, PMC2 [, int flags[,key]);
Copies C<PMC2> into C<PMC1>. The C<flags> parameter notes whether
a deep copy should be done. (Possibly other things as well, if someone
thinks of something reasonable)
=item morph
void morph(PMC, type[, key]);
Tells the PMC to change itself into a PMC of the specified type.
=item move_to
BOOL move_to(void *, PMC);
Tells the PMC to move its contents to a block of memory starting at
the passed address. Used by the garbage collector to compact memory,
this call can return a false value if the move can't be done for some
reason. The pointer is guaranteed to point to a chunk of memory at
least as large as that returned by the C<real_size> vtable function.
=item real_size
IV real_size(PMC[, key]);
Returns an integer value that represents the real size of the data
portion, excluding the vtable, of the PMC.
=item destroy
void destroy(PMC[, key]);
Destroys the variable the PMC represents, leaving it undef.
=item get_integer
INT get_integer(PMC[, key]); ##
Returns an integer value of the appropriate type for the PMC.
=item get_number
NUM get_number(PMC[, key]); ##
Returns a floating point value of the appropriate type for the PMC.
=item get_string
STR get_string(PMC[, key]); ##
Returns a string value of the appropriate type for the PMC.
=item get_bool
BOOL get_bool(PMC[, key]); ##
Returns TRUE if the PMC is true, or FALSE if it isn't.
=item get_value
void * get_value(PMC[, key]);
Returns a pointer to the beginning of currently "OK" data; the type of
this data must be determined by examining the PMCs C<type>. This must
only be used by other vtable functions inside the core, and must never
be used if the PMC is of a type defined by a user outside the core,
unless you know what you're doing. (eg, comparing C<get_value>s from two
PMCs of the same type, or C<set_value(PMC1,get_value(PMC2))>)
=item is_same
BOOL is_same(PMC1, PMC2[, key]);
Returns TRUE if C<PMC1> and C<PMC2> refer to the same value, and FALSE
otherwise.
=item set_integer
void set_integer(PMC, INT[, key]); ##
Sets the integer value of the PMC to C<INT>.
=item set_number
void set_number(PMC, NUM[, key]); ##
Sets the floating-point value of the PMC to C<NUM>.
=item set_string
void set_string(PMC, STR[, key]); ##
Sets the string value of the PMC to C<STR>.
=item set_value
void set_value(PMC, void *[, key]);
See C<get_value>
=item add
void add(PMC1, PMC2, PMC3[, key]); ##
Performs floating-point or integer addition of the values of C<PMC2> and
C<PMC3>, storing the result in C<PMC1>.
=item subtract
void subtract(PMC1, PMC2, PMC3[, key]); ##
Performs floating-point or integer subtraction of the values of C<PMC2> and
C<PMC3>, storing the result in C<PMC1>.
=item multiply
void multiply(PMC1, PMC2, PMC2[, key]); ##
Performs floating-point or integer multiplication of the values of
C<PMC2> and C<PMC3>, storing the result in C<PMC1>.
=item divide
void divide(PMC1, PMC2, PMC3[, key]); ##
Performs floating-point or integer division of the values of C<PMC2> and
C<PMC3>, storing the result in C<PMC1>.
=item modulus
void modulus(PMC1, PMC2, PMC3[, key]); ##
Performs integer modulus of the values of C<PMC2> and C<PMC3>, storing
the result in C<PMC1>.
=item concatenate
void concatenate(PMC1, PMC2, PMC3[, key]); ##
Concatenates the strings in C<PMC2> and C<PMC3>, storing the result in
C<PMC1>.
=item is_equal
BOOL is_equal(PMC, PMC[,key]); ##
Returns TRUE if the two values are equal, and false otherwise.
=item logical_or
void logical_or(PMC1, PMC2, PMC3[, key]); ##
Sets C<PMC1> to a TRUE value if either of C<PMC2> or C<PMC3> have TRUE
values, and a FALSE value otherwise.
=item logical_and
void logical_and(PMC1, PMC2, PMC2[, key]); ##
Sets C<PMC1> to a TRUE value if both C<PMC2> and C<PMC3> have TRUE
values, and a FALSE value otherwise.
=item logical_not
void logical_not(PMC1, PMC2[,key]); ##
Sets C<PMC1> to a TRUE value if C<PMC2> has a FALSE value, and a FALSE
value otherwise.
=item match
void match(PMC1, PMC2, REGEX[, key]);
Performs a regular expression match on C<PMC2> against the expression
C<REGEX>, placing the results in C<PMC1>.
=item repeat (x)
void repeat(PMC1, PMC2, PMC3[, key]); ##
Performs the following sequence of operations: finds the string value
from C<PMC2>; finds an integer value I<n> from C<PMC3>; replicates the
string I<n> times; stores the resulting string in C<PMC1>.
=item nextkey (x)
void nextkey(PMC1, PMC2, start_key[, key]);
Looks up the key C<start_key> in C<PMC2> and then stores the key after
it in C<PMC1>. If start_key is C<undef>, the first key is returned,
and C<PMC1> is set to undef if there is no next key.
=item exists (x)
BOOL exists(PMC1[, key]);
Returns TRUE if the specified PMC exists, or FALSE if it doesn't.
=back
Generally speaking, all functions can be valid on all data types. For
example, calling the C<set_integer> function on an array PMC is the
equivalent of doing C<$#PMC = 12;> at the perl language level.
=head1 TODO
The effects of each function on scalar, array, hash, list, and IO
PMCs needs to be hashed out.
=head1 REFERENCES
PDD 3: Perl's Internal Data Types.
=head1 ACKNOWLEDGEMENTS
Simon Cozens is responsible for most of the function descriptive
text. Mistakes in the text (and thinking) are mine, though.
=head1 FOOTNOTES
Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
[EMAIL PROTECTED] have teddy bears and even
teddy bears get drunk