The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

PMCs

PMCs are one of the four fundamental data types in Parrot, and definitely one of the most useful. A PMC can contain a single scalar value (integer, floating point number, string), an array of values, a subroutine, a namespace, or an entire list of other data types as well. PMCs are the basis for all higher order data types in Parrot, and are flexible enough to be used for any purpose that an HLL needs.

All the common PMC types are included in the Parrot repository and built directy into libparrot and the parrot executable. However, the system is not rigid; new PMC types can be defined externally and loaded into Parrot at a later time. In this way, HLLs and libraries and applications can add new data types to Parrot at the C code level, which helps to ensure speed and efficiency. PMCs loaded this way are called Dynamic PMCs or dynpmcs.

PIR Classes

It's worth a quick diversion here to talk about the difference between a pure PIR class object, and a PMC. Even though classes written in PIR can inherit from an existing PMC type, they aren't all their own type of PMC. In fact, classes written in PIR are all of the Object PMC type. In order to add a new fundamental PMC type to Parrot, it needs to be written in C well, a superset of C anyway and it needs to be compiled using the PMC compiler.

Writing PMCs

In the strictest sense, PMCs are written in C and are compiled by your local C compiler into machine code for linking with libparrot or the parrot executable. However, Parrot's build process makes use of a special PMC compiler program that converts PMCs defined in a special C-like script to ordinary C code. The PMC compiler adds all the necessary boiler plate code and installs the PMC type into Parrot for use. The PMC script is like a macro superset although the functionality is a litte bit more involved then is available in the normal C preprocessor over the C language. All valid C is valid in PMC scripts, but there are also a few additions that help to make common tasks a little easier.

The PMC script was born of conflicting necessities. The internals of Parrot are all written according to the ISO C89 standard for maximum portability. However, PIR and languages that are built on top of Parrot are typically object-oriented (or have some OO capabilities). PMCs are like classes, they have data and methods, and they can inherit from parent PMCs.

C is low-level and portable, which is desirable. But Parrot needed some support for OO features that C doesn't have, and the C preprocessor can't support directly. To support the necessary features, and to make the task of writing PMCs just a little bit easier, the Parrot developers created a PMC compiler program that takes a special PMC script and converts it into standard ISO C89.

PMC Files

PMC files have a .pmc file extension.

pmclass Definitions

A PMC file can contain a PMC class definition and any other helper functions or data structure definitions that are needed to support the PMC. To define a PMC class in the PMC file, you use the pmclass statement. Everything outside the pmclass definition will be ignored by the PMC compiler. Inside the pmclass defintion are going to be all the VTABLE and METHOD declarations for the PMC.

A standard definition can contain a number of parts. Here's a pseudo-grammar for them:

  pmclass CLASSNAME [extends PARENT]? [provides INTERFACE] [FLAGS]* {
  
      /* VTABLE and METHODs defined here. */
  
  }

The extends keyword is optional, but allows us to specify that this PMC class is a subtype of the given type. If we have an extends in the definition, we can use the SUPER keyword throughout the PMC file to refer to the parent type.

The FLAGS are a series of flags that can be specified to determine how the PMC behaves and how it's constructed internally. The need_ext flag assigns a special PMC_EXT data structure to the PMC structure internally. PMC_EXT is necessary to handle data sharing between threads or interpreters, storing attributes in the PMC, and a few other uses as well. The singleton flag means that there can only be one instantiated object of this class.

The provides keyword is used to show that the PMC provides certain standard interfaces. For instance, you can specify provides array and then Parrot will enable us to write things like $P0[2] in PIR code to access the PMC using integer indices. provides hash means that we can use string and PMC keys to access values in the PMC.

INTERP, SUPER, SELF, and STATICSELF

PMC Compiler

Custom Data Structures

VTABLE Function Definitions

VTABLE Functions Parameters

VTABLE functions are defined just like ordinary C functions, almost. Here's a normal definition for a VTABLE method:

  VTABLE VTABLENAME (PARAMETERS) {
    /* ordinary C here, almost */
  }

You can't just name your VTABLE functions anything you want. There is a predefined list of VTABLE function names, and you must name it exactly the same as the one you are trying to implement. The PARAMETERS list is pretty particular as well: Each VTABLE function type has a specific parameter list that must be implemented exactly or else the compiler will throw a warning.

Methods

VTABLES are standard, but they're rigid. They need to have the exact name that Parrot expects, and they need to have the exact function signature that Parrot expects too. VTABLES are responsible for the low-level basic access operations that all data types need to implement. However, to get more out of your PMCs, we need a more flexible want to interact with them.

Enter methods, which are ways to extend the functionality of your PMC in ways that the PMC needs. Methods allow the developer to add all sorts of arbitrary functionality to a PMC that the VTABLE functions themselves cannot define.

Dynpmcs

Loading dynpmcs

########################################################################## # PSEUDOPOD LEGEND # # Interior Sequences # .................. # link anchor (source) # bold text # monospace text # E<> named character # file name # superscript # subscript # italicized text # L<> link to other manpage (see ) # firstterm # footnote # quoted text # replaceable item # text with non-breaking spaces # cited title for book, etc. # URL # a single index term of the form: # primary:sortas;secondary:sortas;tertiary:sortas;;ETC # where ETC is either (see term) or (see also term) # only primary term is required # link anchor (destination) # # Heads # ..... # head0 chapter title # head{1-4} section title (4 levels) # # Command Paragraphs (begin/end Blocks) # ..................................... # blockquote quotation # comment ignored text # caution admonition # epigraph quotation # example container # figure CAPTION figure # important admonition # note admonition # programlisting literal text # screen literal text # sidebar container # table html [CAPTION] table rendered in HTML # table picture [CAPTION] table rendered in plain text # tip admonition # warning admonition # # # Command Paragraphs (for Blocks) # ............................... # This structure will be used only for comments. For example: # # =for editor # Check my spelling on this. # =end # # This will be rendered as a visible comment in the final output # with a label at the top addressing it to "editor". The exception is # =for ignore which will always be ignored by the parser. # # Tables # ...... # A 2x2 table with top header row looks like this: # # =begin table An Example Table # =headrow # =row # =cell Header for first column (row 1, col 1) # =cell Header for 2nd column (row 1, col 2) # =bodyrows # =cell Cell for row 2, col 1 # =cell Cell for row 2, col 2 # =end table # # For more information on PSEUDOPOD, write to tools@oreilly.com ##########################################################################

# Local variables: # c-file-style: "parrot" # End: # vim: expandtab shiftwidth=4:

4 POD Errors

The following errors were encountered while parsing the POD:

Around line 5:

A non-empty Z<>

Around line 23:

Deleting unknown formatting code N<>

Around line 32:

Deleting unknown formatting code N<>

Around line 144:

Deleting unknown formatting code A<>

Deleting unknown formatting code G<>

Deleting unknown formatting code H<>

Deleting unknown formatting code A<>

Deleting unknown formatting code M<>

Deleting unknown formatting code N<>

Deleting unknown formatting code Q<>

Deleting unknown formatting code R<>

Deleting unknown formatting code T<>

Deleting unknown formatting code U<>

An empty L<>

An empty E<>