NAME

docs/dev/pcc_methods.pod - Parrot Calling Conventions in C

DESCRIPTION

This document address issues relating to PCCMETHOD and the Parrot Calling Conventions.

OVERVIEW

A PCCMETHOD is a PMC method that follows the Parrot Calling Conventions (a.k.a. PCC). This allows PIR code to call PMC methods using slurpy, named, and other types of arguments as specified in PDD03. This offers flexibility not found in a PMC METHOD or a vtable function using C calling conventions.

PCCINVOKE is used to call a method using the Parrot Calling Conventions. It uses the standard find_method()/invoke() approach that the callmethodcc opcode would. You can use PCCINVOKE in any PMC method (including vtable methods), even if they are not PCCMETHOD's. You can call methods that are not implemented with PCCMETHOD, too.

SYNTAX

PCCMETHOD

To declare that a method in a PMC should take arguments using the Parrot Calling Conventions, prefix its name with the keyword PCCMETHOD. The PCC parameter list is put where you would normally put the C parameter list. Do not specify a return type for PCCMETHOD's; the true signature of the return is specified inside the method using RETURN, described below.

  PCCMETHOD PlayRandomSong() {
      ...
  }

  PCCMETHOD PlaySong(STRING *artist, STRING *title) {
      ...
  }

For full details of the parameter list syntax, see "Parameter List Syntax".

RETURN

To return arguments using the Parrot Calling Conventions, which you should do if you have implemented a PCCMETHOD (unless it returns no arguments, of course), use the RETURN keyword. This takes a signature as specified in the "Parameter List Syntax" section.

  RETURN(PMC *status, INTVAL count);

PCCINVOKE

To call a method on an object using the Parrot Calling Conventions, use PCCINVOKE. It takes 3 arguments, followed by the signature of the call and the arguments as specified in the "Parameter List Syntax" section.

The first three arguments, in order, are:

Any return arguments appear, with the return signature, to the left of the call and in parentheses.

For example:

  PCCINVOKE(interp, monkey, "eat", PMC* banana);

  (PMC *pooh) = PCCINVOKE(interp, monkey, "excrete");

  (PMC *status, INTVAL count) = PCCINVOKE(interp, player, "PlaySong", artist, title);

  PCCINVOKE(interp, SELF, value :named("key") :optional)

Parameter List Syntax

The syntax for a PCC parameter list is a comma separated list of zero or more parameters. Each parameter takes the form:

  { INTVAL | NUMVAL | STRING* | PMC* } NAME [ ADVERBS ]

That is, a register type, followed by a name, optionally followed by one or more flags specified as adverbs. The list of supported adverbs is listed in docs/pdds/pdd03_calling_conventions.pod, the calling conventions design document.

Note that unlike PIR, single quotes cannot be used to quote values in C-based PCC calls.

Also note that in line with the Parrot code standards, you should put the pointer symbol next to the variable,

  PMC *param :optional    # Good

not next to the type.

  PMC* param :optional    # Bad

OTHER CONSIDERATIONS

Performance

When a METHOD or vtable function is called, NCI is used to map the arguments held in the current Parrot_Context into the C calling conventions. That is, you still end up involving the Parrot Calling Conventions anyway, so there is no reason to expect a PCCMETHOD to be any slower. It may well be faster. It's probably best to just not care. :-)

It is clearly true that PCCINVOKE is going to be more costly than an invocation of a C function from another C function, if you do the call directly at the C level. However, if you do that, you are ignoring any method overrides if you have been subclassed and you wouldn't want to do that now, would you?