Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 304 lines (195 sloc) 9.419 kb
1ae09dba » rurban
2014-04-15 'Updated 'parrot.github.com'
1 # Copyright (C) 2001-2012, Parrot Foundation.
2
3 =pod
4
5 =head1 NAME
6
7 docs/vtables.pod - Parrot Vtables
8
9 =head1 DESCRIPTION
10
11 This is a guide to creating your own PMC (Polymorphic Container) classes. It
12 tells you what you need to write in order to add new variable types to Parrot.
13
14 =head2 Overview
15
16 The guts of the Parrot interpreter are by design ignorant (or, if you want to
17 be less disparaging, agnostic) of the intricacies of variable type behavior.
18 The standard example is the difference between Perl scalars and Python scalars.
19 In Perl, if you have
20
21 $a = "a9";
22 $a++;
23
24 you end up with C<$a> being C<b0>. This is because of the magic of the Perl
25 increment operator. In Python, on the other hand, you'd get a runtime error.
26
27 =over 3
28
29 =item *
30
31 To be perfectly honest, this is a slightly flawed example, since it's
32 unlikely that there will be a distinct "Python scalar" PMC class. The
33 Python compiler could well infer variables by their type such that C<a>
34 would be a C<PythonString> and C<b> would be a C<PythonNumber>. But the
35 point remains - incrementing a C<PythonString> is very different from
36 incrementing a C<PerlScalar>.
37
38 =back
39
40 Since the behavior is a function of the "type" of the PMC, it's natural to
41 consider the various different types of PMC as classes in an object-oriented
42 system. The Parrot interpreter calls methods on the individual PMC objects to
43 manipulate them. So the example above would translate to something like:
44
45 =over 3
46
47 =item 1.
48
49 Construct a new PMC in the PerlScalar class.
50
51 =item 2.
52
53 Call a method setting its string value to C<"a9">.
54
55 =item 3.
56
57 Call a method to tell it to increment itself.
58
59 =back
60
61 And if you replace PerlScalar with PythonString, you get different behavior but
62 to the fundamental guts of the interpreter, the instructions are the same. PMCs
63 are an abstract virtual class; the interpreter calls a method, the PMC object
64 does the right thing, and the interpreter shouldn't have to care particularly
65 what that right thing happens to be.
66
67 Hence, adding a new data type to Parrot is a question of providing methods
68 which implement that data type's expected behavior. Let's now look at how one
69 is supposed to do this.
70
71 =head2 Starting out
72
73 If you're adding data types to the core of Parrot, you should be creating a
74 file in the F<src/pmc/> subdirectory; this is where all the built-in PMC
75 classes live. (And a good source of examples to plunder even if you're not
76 writing a core data type.)
77
78 You should almost always start by running F<tools/dev/gen_class.pl> to
79 generate a skeleton for the class. Let's generate a number type for
80 the beautifully non-existent Fooby language:
81
82 % perl tools/dev/gen_class.pl FoobyNumber > src/pmc/foobynumber.pmc
83
84 This will produce a skeleton PMC file (to be preprocessed into ordinary C
85 code by the F<tools/build/pmc2c.pl> program) with stubs for all the methods
86 you need to fill in. Actually, there are more stubs here then you probably
87 I<need> to fill in. Your PMC isn't going to want to support all these
88 methods, and in many cases you may want to fall back to default behavior
89 instead of implementing a dummy method.> The function C<init> allows you to
90 set up anything you need to set up.
91
92 Now you'll have to do something a little different depending on whether you're
93 writing a built-in class or an extension class. If you're writing a non-core
94 PMC, called a "dynpmc", you need to add the argument C<dynpmc> to the line
95 that starts with C<pmclass>. Here's an example:
96
97 pmclass FooByNumber dynpmc {
98 ...
99
100 This alerts the PMC compiler that the PMC type should not be hard-coded into
101 Parrot, and that the PMC definition needs to be loaded in to Parrot
102 dynamically when the user requires it.
103
104 To finish up adding a built-in class:
105
106 =over 4
107
108 =item 1.
109
110 Add src/pmc/YOURCLASS.pmc to the MANIFEST.
111
112 =item 2.
113
114 Run C<make realclean>, and then run F<Configure.pl> to add your new PMC to
115 the set of built-in PMCs.
116
117 =back
118
119 =head2 What You Can and Cannot Do
120
121 The usual way to continue from the F<tools/dev/gen_class.pl>-generated
122 skeleton is to define a structure that will hook onto the C<data>, if your
123 data type needs to use that, and then also define some user-defined flags.
124
125 Flags are accessed by C<< pmc->flags >>. Most of the bits in the flag word are
126 reserved for use by parrot itself, but a number of them have been assigned for
127 general use by individual classes. These are referred to as
128 C<Pobj_private0_FLAG> .. C<Pobj_private7_FLAG>.
129
130 Normally, you will want to alias these generic bit names to something more
131 meaningful within your class:
132
133 enum {
134 Foobynumber_is_bignum = Pobj_private0_FLAG,
135 Foobynumber_is_bigint = Pobj_private1_FLAG,
136 ....
137 };
138
139 To manipulate the flags, use the macros listed in F<pobj.h>.
140
141 PMCs also have the ability to store an arbitrary number of user-defined
142 attribute values using the C<ATTR> keyword.
143
144 =head2 Multimethods
145
146 One slightly (potentially) tricky element of implementing vtables is that
147 several of the vtable functions have variant forms depending on the type of
148 data that they're being called with.
149
150 For instance, the C<set_integer> method has multiple forms; the default
151 C<set_integer> means that you are being called with a PMC, and you should
152 probably use the C<get_integer> method of the PMC to find its integer value;
153 C<set_integer_native> means you're being passed an C<INTVAL>. The final form is
154 slightly special; if the interpreter calls C<set_integer_same>, you know that
155 the PMC that you are being passed is of the same type as you. Hence, you can
156 break the class abstraction to save a couple of dereferences - if you want to.
157
158 Similar shortcuts exist for strings, (C<native> and C<same>) and floating point
159 numbers.
160
161 =head2 Implementing VTABLE Interfaces
162
163 The master list of VTABLE interfaces can be found in F<src/vtable.tbl> in
164 the root directory of the Parrot source, with documentation in
165 F<docs/pdds/pdd17_pmc.pod>. A few of these are very important, for
166 instance:
167
168 =over 3
169
170 =item C<type>
171
172 Return the enumeration value of your class.
173
174 =item C<name>
175
176 Return a string containing your class name.
177
178 =item C<init>
179
180 Initialization. Parrot makes exactly one call to either C<init> or
181 C<init_pmc> at PMC construction time.
182
183 =item C<init_pmc>
184
185 Alternative entry point for initialization that takes a PMC argument.
186 Parrot makes exactly one call to either C<init> or C<init_pmc> at PMC
187 construction time.
188
189 NOTE: It is strongly suggested that C<init_pmc(PMCNULL)> be equivalent to
190 C<init()>.
191
192 =item C<is_equal>
193
194 True if the passed-in PMC has the same B<value> as you. For instance, a Perl
195 integer and a Python integer could have the same value, but could not be the
196 same thing as defined by C<is_same>.
197
198 =item C<clone>
199
200 Copy your data and state into the passed-in destination PMC.
201
202 =back
203
204 Others are methods you may or may not need, depending on your type:
205
206 =over 3
207
208 =item C<morph>
209
210 Turn yourself into the specified type.
211
212 =item C<destroy>
213
214 Do any data shut-down and finalization you need to do. To have this method
215 called, you must set the C<Pobj_custom_destroy_FLAG>.
216
217 =item C<get_integer>
218
219 Return an integer representation of yourself.
220
221 =item C<get_number>
222
223 Return a floating-point representation of yourself.
224
225 =item C<get_string>
226
227 Return a string representation of yourself (a STRING* object), this should be a
228 B<copy> of whatever string you are holding, not just a pointer to your own
229 string so that anything that calls this method can happily modify this value
230 without making a mess of your guts.
231
232 =item C<get_bool>
233
234 Return a boolean representation of yourself.
235
236 =item C<get_value>
237
238 Return your private data as a raw pointer.
239
240 =item C<is_same>
241
242 True if the passed-in PMC refers to exactly the same B<data> as you. (Contrast
243 C<is_equal>)
244
245 =item C<set_integer>
246
247 Set yourself to the passed-in integer value. This is an integer multimethod.
248
249 =item C<set_number>
250
251 Set yourself to the passed-in float value. This is a floating-point
252 multimethod.
253
254 =item C<set_string>
255
256 Set yourself to the passed-in string. This is a string multimethod.
257
258 =item C<add>
259
260 Fetch the number part of C<value> and add your numeric value to it, storing the
261 result in C<dest>. (Probably by calling its C<set_integer> or C<set_number>
262 method) This is a numeric multimethod.
263
264 =item C<subtract>
265
266 Fetch the number part of C<value> and subtract your numeric value from it,
267 storing the result in C<dest>. (Probably by calling its C<set_integer> or
268 C<set_number> method) This is a numeric multimethod.
269
270 =item C<multiply>
271
272 =item C<divide>
273
274 =item C<modulus>
275
276 You get the picture.
277
278 =item C<concatenate>
279
280 Fetch the string part of C<value> and concatenate it to yourself, storing the
281 result in C<dest>. (Probably by calling its C<set_string> method) This is a
282 string multimethod.
283
284 =item C<repeat>
285
286 Repeat your string representation C<value> times and store the result in
287 C<dest>.
288
289 =back
290
291 If any method doesn't fit into your class, just don't implement it and don't
292 provide an empty function body. The default class, which all classes inherit
293 from will throw an exception if the missing method ever gets called.
294
295 If your class is a modification of an existing class, you may wish to use
296 inheritance. At the beginning of your VTABLE specification in
297 src/pmc/YOURCLASS.pmc, add the C<extends SUPERCLASS> phrase. For example:
298
299 pmclass PackedArray extends Array { ...
300
301 See the POD documentation in F<tools/build/pmc2c.pl> for a list of useful
302 keywords that you may use in the .pmc file.
303
304 =cut
Something went wrong with that request. Please try again.