11 object.ops - Class and Object Opcodes
15 Parrot's library of object ops
17 When making changes to any ops file, run C<make bootstrap-ops> to regenerate
18 all generated ops files.
24 =item B<callmethodcc>(invar PMC, in STR)
26 Call method $2 with invocant $1 and generate a new return continuation.
27 The invocant ($1) is used for method lookup. The object is passed as
28 the first argument in B<set_args>.
30 Throws a Method_Not_Found_Exception for a non-existent method.
32 =item B<callmethodcc>(invar PMC, invar PMC)
34 Like above but use the Sub object $2 as method.
36 =item B<callmethod>(invar PMC, in STR, invar PMC)
38 =item B<callmethod>(invar PMC, invar PMC, invar PMC)
40 Like above, but use continuation $3 instead of creating a new continuation.
44 =item B<tailcallmethod>(invar PMC, in STR)
46 =item B<tailcallmethod>(invar PMC, invar PMC)
48 Make a tailcall to method $2 with invocant $1.
52 op callmethodcc(invar PMC, in STR) :object_base :flow {
53 PMC * const object = $1;
54 STRING * const meth = $2;
55 opcode_t * const next = expr NEXT();
57 PMC * const method_pmc = VTABLE_find_method(interp, object, meth);
58 opcode_t *dest = NULL;
60 Parrot_pcc_set_pc_func(interp, CURRENT_CONTEXT(interp), next);
62 if (!PMC_IS_NULL(method_pmc)) {
63 PMC * const signature = Parrot_pcc_get_signature(interp,
64 CURRENT_CONTEXT(interp));
65 if (!PMC_IS_NULL(signature))
66 Parrot_pcc_set_object(interp, signature, object);
68 interp->current_cont = NEED_CONTINUATION;
69 dest = VTABLE_invoke(interp, method_pmc, next);
72 PMC * const _class = VTABLE_get_class(interp, object);
73 if (PMC_IS_NULL(_class)) {
74 dest = Parrot_ex_throw_from_op_args(interp, next,
75 EXCEPTION_METHOD_NOT_FOUND,
76 "Method '%Ss' not found for non-object", meth);
79 dest = Parrot_ex_throw_from_op_args(interp, next,
80 EXCEPTION_METHOD_NOT_FOUND,
81 "Method '%Ss' not found for invocant of class '%Ss'", meth,
82 VTABLE_get_string(interp, _class));
89 op callmethodcc(invar PMC, invar PMC) :object_base :flow {
91 opcode_t * const next = expr NEXT();
92 PMC * signature = Parrot_pcc_get_signature(interp,
93 CURRENT_CONTEXT(interp));
95 Parrot_pcc_set_pc_func(interp, CURRENT_CONTEXT(interp), next);
97 if (!PMC_IS_NULL(signature))
98 Parrot_pcc_set_object(interp, signature, $1);
99 interp->current_cont = NEED_CONTINUATION;
100 dest = VTABLE_invoke(interp, $2, next);
105 op callmethod(invar PMC, in STR, invar PMC) :object_base :flow {
106 PMC * const object = $1;
107 STRING * const meth = $2;
108 opcode_t * const next = expr NEXT();
110 PMC * const method_pmc = VTABLE_find_method(interp, object, meth);
111 opcode_t *dest = NULL;
112 PMC * signature = Parrot_pcc_get_signature(interp,
113 CURRENT_CONTEXT(interp));
115 Parrot_pcc_set_pc_func(interp, CURRENT_CONTEXT(interp), next);
117 if (PMC_IS_NULL(method_pmc)) {
118 dest = Parrot_ex_throw_from_op_args(interp, next, EXCEPTION_METHOD_NOT_FOUND,
119 "Method '%Ss' not found for invocant of class '%Ss'", meth,
120 VTABLE_get_string(interp, VTABLE_get_class(interp, object)));
123 if (!PMC_IS_NULL(signature))
124 Parrot_pcc_set_object(interp, signature, object);
125 interp->current_cont = $3;
126 dest = (opcode_t *)VTABLE_invoke(interp, method_pmc, next);
131 op callmethod(invar PMC, invar PMC, invar PMC) :object_base :flow {
132 PMC * const object = $1;
133 PMC * const method_pmc = $2;
134 opcode_t * const next = expr NEXT();
137 PMC * signature = Parrot_pcc_get_signature(interp,
138 CURRENT_CONTEXT(interp));
140 Parrot_pcc_set_pc_func(interp, CURRENT_CONTEXT(interp), next);
142 if (!PMC_IS_NULL(signature))
143 Parrot_pcc_set_object(interp, signature, object);
144 interp->current_cont = $3;
145 dest = (opcode_t *)VTABLE_invoke(interp, method_pmc, next);
149 op tailcallmethod(invar PMC, in STR) :object_base :flow {
150 opcode_t * const next = expr NEXT();
151 PMC * const object = $1;
152 STRING * const meth = $2;
153 PMC * const method_pmc = VTABLE_find_method(interp, object, meth);
156 PMC * signature = Parrot_pcc_get_signature(interp,
157 CURRENT_CONTEXT(interp));
159 if (PMC_IS_NULL(method_pmc)) {
160 dest = Parrot_ex_throw_from_op_args(interp, next, EXCEPTION_METHOD_NOT_FOUND,
161 "Method '%Ss' not found for invocant of class '%Ss'", meth,
162 VTABLE_get_string(interp, VTABLE_get_class(interp, object)));
165 interp->current_cont = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp));
166 PObj_get_FLAGS(interp->current_cont) |= SUB_FLAG_TAILCALL;
167 if (!PMC_IS_NULL(signature))
168 Parrot_pcc_set_object(interp, signature, object);
169 dest = (opcode_t *)VTABLE_invoke(interp, method_pmc, next);
174 op tailcallmethod(invar PMC, invar PMC) :object_base :flow {
175 opcode_t * const next = expr NEXT();
176 PMC * const object = $1;
177 PMC * const method_pmc = $2;
180 PMC * signature = Parrot_pcc_get_signature(interp,
181 CURRENT_CONTEXT(interp));
183 interp->current_cont = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp));
184 PObj_get_FLAGS(interp->current_cont) |= SUB_FLAG_TAILCALL;
186 if (!PMC_IS_NULL(signature))
187 Parrot_pcc_set_object(interp, signature, object);
188 dest = (opcode_t *)VTABLE_invoke(interp, method_pmc, next);
192 =item B<addmethod>(invar PMC, in STR, invar PMC)
194 Adds $3 as a method named $2 to $1.
198 inline op addmethod(invar PMC, in STR, invar PMC) :object_classes {
199 VTABLE_add_method(interp, $1, $2, $3);
203 =item B<can>(out INT, invar PMC, in STR)
205 Sets result $1 to the result of the "can" vtable function for PMC $2,
210 inline op can(out INT, invar PMC, in STR) :object_base {
211 $1 = VTABLE_can(interp, $2, $3);
215 =item B<does>(out INT, invar PMC, in STR)
217 Sets result $1 to the result of the "does" vtable function for PMC $2,
218 given the role of name $3.
222 inline op does(out INT, invar PMC, in STR) :object_base {
223 $1 = $3 ? VTABLE_does(interp, $2, $3) : 0;
226 =item B<does>(out INT, invar PMC, in PMC)
228 Sets result $1 to the result of the "does" vtable function for PMC $2,
233 inline op does(out INT, invar PMC, in PMC) :object_base {
234 $1 = $3 ? VTABLE_does_pmc(interp, $2, $3) : 0;
237 =item B<isa>(out INT, invar PMC, in STR)
239 =item B<isa>(out INT, invar PMC, in PMC)
241 Sets result $1 to the result of the "isa" vtable function for PMC $2,
246 inline op isa(out INT, invar PMC, in STR) :object_base {
247 $1 = $3 ? VTABLE_isa(interp, $2, $3) : 0;
250 inline op isa(out INT, invar PMC, in PMC) :object_base {
251 $1 = $3 ? VTABLE_isa_pmc(interp, $2, $3) : 0;
254 ###############################################################################
256 =item B<newclass>(out PMC, in STR)
258 Create a new Parrot-style class, named $2, and puts the new PMC for it
261 =item B<newclass>(out PMC, in PMC)
263 Create a new Parrot-style class, with the name given in $2 as a key,
264 namespace, or string PMC.
268 inline op newclass(out PMC, in STR) :object_classes {
269 PMC * const name = Parrot_pmc_new(interp, enum_class_String);
270 VTABLE_set_string_native(interp, name, $2);
271 $1 = Parrot_pmc_new_init(interp, enum_class_Class, name);
274 inline op newclass(out PMC, in PMC) :object_classes {
275 $1 = Parrot_pmc_new_init(interp, enum_class_Class, $2);
278 =item B<subclass>(out PMC, in PMC)
280 =item B<subclass>(out PMC, in PMC, in STR)
282 =item B<subclass>(out PMC, in PMC, in PMC)
284 Create a new class, put in $1, that is a subclass of $2. $3, if available
285 and not null, is the name of the new class--if not, the subclass is an
290 inline op subclass(out PMC, in PMC) :object_classes :flow {
291 PMC * const parent_class = Parrot_oo_get_class(interp, $2);
292 opcode_t * const next = expr NEXT();
294 if (PMC_IS_NULL(parent_class)) {
295 opcode_t *handler = Parrot_ex_throw_from_op_args(interp, next,
297 "Class '%Ss' doesn't exist", VTABLE_get_string(interp, $2));
298 goto ADDRESS(handler);
300 $1 = Parrot_pmc_new(interp, enum_class_Class);
301 VTABLE_add_parent(interp, $1, parent_class);
305 inline op subclass(out PMC, in PMC, in STR) :object_classes :flow {
306 PMC * const parent_class = Parrot_oo_get_class(interp, $2);
307 opcode_t * const next = expr NEXT();
309 if (PMC_IS_NULL(parent_class)) {
310 opcode_t * handler = Parrot_ex_throw_from_op_args(interp, next,
312 "Class '%Ss' doesn't exist", VTABLE_get_string(interp, $2));
313 goto ADDRESS(handler);
315 $1 = Parrot_oo_newclass_from_str(interp, $3);
316 VTABLE_add_parent(interp, $1, parent_class);
320 inline op subclass(out PMC, in PMC, in PMC) :object_classes :flow {
321 PMC * const parent_class = Parrot_oo_get_class(interp, $2);
322 opcode_t * const next = expr NEXT();
324 if (PMC_IS_NULL(parent_class)) {
325 opcode_t *handler = Parrot_ex_throw_from_op_args(interp, next,
327 "Class '%Ss' doesn't exist", VTABLE_get_string(interp, $2));
328 goto ADDRESS(handler);
330 $1 = Parrot_pmc_new_init(interp, enum_class_Class, $3);
331 VTABLE_add_parent(interp, $1, parent_class);
335 =item B<subclass>(out PMC, in STR)
337 =item B<subclass>(out PMC, in STR, in STR)
339 =item B<subclass>(out PMC, in STR, in PMC)
341 Create a new class, put in $1, that is a subclass of the class named $2.
342 $3, if available and not null, is the name of the new class--if not, the
343 subclass is an anonymous subclass.
348 op subclass(out PMC, in STR) :object_classes :flow {
349 PMC * const parent_class = Parrot_oo_get_class_str(interp, $2);
350 opcode_t * const next = expr NEXT();
352 if (PMC_IS_NULL(parent_class)) {
353 opcode_t *handler = Parrot_ex_throw_from_op_args(interp, next,
355 "Class '%Ss' doesn't exist", $2);
356 goto ADDRESS(handler);
359 $1 = Parrot_pmc_new(interp, enum_class_Class);
360 VTABLE_add_parent(interp, $1, parent_class);
364 op subclass(out PMC, in STR, in STR) :object_classes :flow {
365 PMC * const parent_class = Parrot_oo_get_class_str(interp, $2);
366 opcode_t * const next = expr NEXT();
368 if (PMC_IS_NULL(parent_class)) {
369 opcode_t *handler = Parrot_ex_throw_from_op_args(interp, next,
371 "Class '%Ss' doesn't exist", $2);
372 goto ADDRESS(handler);
375 $1 = Parrot_oo_newclass_from_str(interp, $3);
376 VTABLE_add_parent(interp, $1, parent_class);
380 op subclass(out PMC, in STR, in PMC) :object_classes :flow {
381 PMC * const parent_class = Parrot_oo_get_class_str(interp, $2);
382 opcode_t * const next = expr NEXT();
384 if (PMC_IS_NULL(parent_class)) {
385 opcode_t *handler = Parrot_ex_throw_from_op_args(interp, next,
387 "Class '%Ss' doesn't exist", $2);
388 goto ADDRESS(handler);
391 $1 = Parrot_pmc_new_init(interp, enum_class_Class, $3);
392 VTABLE_add_parent(interp, $1, parent_class);
396 ###############################################################################
398 =item B<get_class>(out PMC, in STR)
400 =item B<get_class>(out PMC, in PMC)
402 Find the PMC for a class, by string name, key or namespace. This op does
403 C<not> find the class of an instance of an object. use C<typeof> for that.
407 inline op get_class(out PMC, in STR) :object_classes {
408 $1 = Parrot_oo_get_class_str(interp, $2);
411 inline op get_class(out PMC, in PMC) :object_classes {
412 $1 = Parrot_oo_get_class(interp, $2);
415 ###############################################################################
417 =item B<class>(out PMC, invar PMC)
419 Get the class PMC for the object in $2 and put it in $1.
423 inline op class(out PMC, invar PMC) :object_classes {
424 $1 = VTABLE_get_class(interp, $2);
427 ##################################################
430 =item B<addparent>(invar PMC, invar PMC)
432 Add class $2 to the list of parent classes for $1.
436 inline op addparent(invar PMC, invar PMC) :object_classes {
437 VTABLE_add_parent(interp, $1, $2);
440 =item B<removeparent>(invar PMC, invar PMC)
442 Remove class $2 from class $1's list of parents.
446 inline op removeparent(invar PMC, invar PMC) :object_classes {
447 VTABLE_remove_parent(interp, $1, $2);
450 =item B<addrole>(invar PMC, invar PMC)
452 Compose the role $2 into $1.
456 inline op addrole(invar PMC, invar PMC) :object_classes {
457 VTABLE_add_role(interp, $1, $2);
460 =item B<addattribute>(invar PMC, in STR)
462 Add the attribute named $2 to the class $1.
466 inline op addattribute(invar PMC, in STR) :object_classes {
467 VTABLE_add_attribute(interp, $1, $2, PMCNULL);
470 =item B<removeattribute>(invar PMC, in STR) B<(unimplemented)>
472 Remove attribute $2 from class $1, specified by name.
476 op removeattribute(invar PMC, in STR) :object_classes {
477 VTABLE_remove_attribute(interp, $1, $2);
480 =item B<getattribute>(out PMC, invar PMC, in STR)
482 Get the attribute $3 from object $2 and put the result in $1.
484 =item B<getattribute>(out PMC, invar PMC, in PMC, in STR)
486 Get the attribute $4 from the parent $3 of object $2 and put the
487 result in $1. (This is useful for storing data for a parent class
488 attribute that is overridden in a child class.) The parent $3 is a
489 class name, namespace, or key PMC.
493 inline op getattribute(out PMC, invar PMC, in STR) :object_classes {
494 $1 = VTABLE_get_attr_str(interp, $2, $3);
497 inline op getattribute(out PMC, invar PMC, in PMC, in STR) :object_classes {
498 $1 = VTABLE_get_attr_keyed(interp, $2, $3, $4);
501 =item B<setattribute>(invar PMC, in STR, invar PMC)
503 Set attribute $2 of object $1 to $3.
505 =item B<setattribute>(invar PMC, in PMC, in STR, invar PMC)
507 Set attribute $3 of the parent $2 of object $1 to $4. (This is useful
508 for storing data for a parent class attribute that is overridden in a
509 child class.) The parent $2 is a class name, namespace, or key PMC.
513 inline op setattribute(invar PMC, in STR, invar PMC) :object_classes {
514 VTABLE_set_attr_str(interp, $1, $2, $3);
517 inline op setattribute(invar PMC, in PMC, in STR, invar PMC) :object_classes {
518 VTABLE_set_attr_keyed(interp, $1, $2, $3, $4);
521 ###############################################################################
523 =item B<inspect>(out PMC, in PMC)
525 Sets $1 to a PMC hash of all introspection data available for $2, keyed on
528 =item B<inspect>(out PMC, in PMC, in STR)
530 Sets $1 to a PMC Hash, Array, String, Integer, or Number value with
531 introspection information corresponding to the requested string name.
535 inline op inspect(out PMC, in PMC) :object_classes {
536 $1 = VTABLE_inspect(interp, $2);
539 inline op inspect(out PMC, in PMC, in STR) :object_classes {
540 $1 = VTABLE_inspect_str(interp, $2, $3);
547 Copyright (C) 2001-2009, Parrot Foundation.
551 This program is free software. It is subject to the same license
552 as the Parrot interpreter itself.
558 * c-file-style: "parrot"
560 * vim: expandtab shiftwidth=4: