fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / ops / object.ops
blob7b3485bf72696f9387f2ec707799ed80da51f5a0
1 /*
3 $Id$
5 object.ops
7 */
9 =head1 NAME
11 object.ops - Class and Object Opcodes
13 =head1 DESCRIPTION
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.
20 =over 4
22 =cut
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.
42 =cut
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.
50 =cut
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);
70     }
71     else {
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);
77         }
78         else {
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));
83         }
84     }
86     goto ADDRESS(dest);
89 op callmethodcc(invar PMC, invar PMC) :object_base :flow {
90     opcode_t        *dest;
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);
102     goto ADDRESS(dest);
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)));
121     }
122     else {
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);
127     }
128     goto ADDRESS(dest);
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();
136     opcode_t *dest;
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);
146     goto ADDRESS(dest);
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);
155     opcode_t *dest;
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)));
163     }
164     else {
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);
170     }
171     goto ADDRESS(dest);
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;
179     opcode_t *dest;
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);
189     goto ADDRESS(dest);
192 =item B<addmethod>(invar PMC, in STR, invar PMC)
194 Adds $3 as a method named $2 to $1.
196 =cut
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,
206 given method $3.
208 =cut
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.
220 =cut
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,
229 given the role $3.
231 =cut
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,
242 given class $3.
244 =cut
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
259 into $1.
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.
266 =cut
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
286 anonymous subclass.
288 =cut
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,
296             EXCEPTION_NO_CLASS,
297             "Class '%Ss' doesn't exist", VTABLE_get_string(interp, $2));
298         goto ADDRESS(handler);
299     }
300     $1 = Parrot_pmc_new(interp, enum_class_Class);
301     VTABLE_add_parent(interp, $1, parent_class);
302     goto ADDRESS(next);
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,
311             EXCEPTION_NO_CLASS,
312             "Class '%Ss' doesn't exist", VTABLE_get_string(interp, $2));
313         goto ADDRESS(handler);
314     }
315     $1 = Parrot_oo_newclass_from_str(interp, $3);
316     VTABLE_add_parent(interp, $1, parent_class);
317     goto ADDRESS(next);
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,
326             EXCEPTION_NO_CLASS,
327             "Class '%Ss' doesn't exist", VTABLE_get_string(interp, $2));
328         goto ADDRESS(handler);
329     }
330     $1 = Parrot_pmc_new_init(interp, enum_class_Class, $3);
331     VTABLE_add_parent(interp, $1, parent_class);
332     goto ADDRESS(next);
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.
345 =cut
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,
354             EXCEPTION_NO_CLASS,
355             "Class '%Ss' doesn't exist", $2);
356         goto ADDRESS(handler);
357     }
359     $1 = Parrot_pmc_new(interp, enum_class_Class);
360     VTABLE_add_parent(interp, $1, parent_class);
361     goto ADDRESS(next);
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,
370             EXCEPTION_NO_CLASS,
371             "Class '%Ss' doesn't exist", $2);
372         goto ADDRESS(handler);
373     }
375     $1  = Parrot_oo_newclass_from_str(interp, $3);
376     VTABLE_add_parent(interp, $1, parent_class);
377     goto ADDRESS(next);
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,
386             EXCEPTION_NO_CLASS,
387             "Class '%Ss' doesn't exist", $2);
388         goto ADDRESS(handler);
389     }
391     $1 = Parrot_pmc_new_init(interp, enum_class_Class, $3);
392     VTABLE_add_parent(interp, $1, parent_class);
393     goto ADDRESS(next);
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.
405 =cut
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.
421 =cut
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.
434 =cut
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.
444 =cut
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.
454 =cut
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.
464 =cut
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.
474 =cut
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.
491 =cut
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.
511 =cut
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
526 name.
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.
533 =cut
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);
543 =back
545 =head1 COPYRIGHT
547 Copyright (C) 2001-2009, Parrot Foundation.
549 =head1 LICENSE
551 This program is free software. It is subject to the same license
552 as the Parrot interpreter itself.
554 =cut
557  * Local variables:
558  *   c-file-style: "parrot"
559  * End:
560  * vim: expandtab shiftwidth=4:
561  */