develooper Front page | perl.perl6.internals | Postings from February 2001

PDD 2, vtables

Thread Previous | Thread Next
From:
Dan Sugalski
Date:
February 5, 2001 14:14
Subject:
PDD 2, vtables
Message ID:
5.0.2.1.0.20010205171325.01aab9b8@24.8.96.48
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 <dan@sidhe.org>
   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
dan@sidhe.org                         have teddy bears and even
                                      teddy bears get drunk


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About