Author: allison
Date: Thu Sep 13 18:17:20 2007
New Revision: 21271

Modified:
   trunk/docs/pdds/draft/pdd17_pmc.pod

Log:
[pdd] Answering a round of questions for the PMC PDD, filling in details on
declaring PMCs, inheritance, and composition.


Modified: trunk/docs/pdds/draft/pdd17_pmc.pod
==============================================================================
--- trunk/docs/pdds/draft/pdd17_pmc.pod (original)
+++ trunk/docs/pdds/draft/pdd17_pmc.pod Thu Sep 13 18:17:20 2007
@@ -14,7 +14,6 @@
 This PDD describes the internal structure and behavior of the Parrot Magic
 Cookie (PMC) data type. 
 
-
 =head1 DESCRIPTION
 
 PMCs implement all internal data types more complex than a simple integer,
@@ -22,109 +21,24 @@
 outside the core of Parrot (in fact, nothing outside the data type's vtable
 routines) should infer anything about a PMC (hence the Magic part).
 
-This does mean, though, that you need to either know
-what functions are available and what they do, or have some method of finding
-out. 
-
-It's faster if you know which vtable entry does what, so that's the method
-parrot uses.
-
+This does mean, though, that you need to either know what functions are
+available and what they do, or have some method of finding out. Parrot defines
+a standard set of functions that each PMC provides. More complex features are
+constructed out of these fundamental building blocks.
 
-=head1 QUESTIONS
+=head1 DESCRIPTION
 
 =over 4
 
-=item *
-
-Where should c-level role implementations live? In src/pmc? What naming
-convention should we use for the files? Singleton role goes to rsingleton.pmc?
-
-=item *
-
-Should we create a pmrole keyword like pmclass? And pmr2c to translate them to
-C? How different are classes and roles at the PMC level?
-
-=item *
-
-<particle> pmclass needs a keyword to specify what roles a class is composed
-from.  We're already using 'does', but in an ad hoc way, from what I can see in
-the little docs there are about 'does'.
-
-=item *
-
-<particle> Do c-level roles have custom flags like PMCs? Class PMC has a custom
-flag for 'instantiated', right now it uses a full int, which I think is a waste
-of space. <allison> 8 bits is pretty limited, and IIRC we've already run into
-the limitation. This runs back to Leo's proposal to make PMCs a little more
-flexible, so we wouldn't have to hold all PMCs to the same 8 bits
-
-=item *
-
-<pmichaud> there is a question about when 'Integer' is not really .Integer
-e.g., in a HLL, the meaning of 'Integer' can be different, and using C<new
-'Integer'> is safe only if in the root of the parrot HLL namespace
-
-<allison> true, the only way to guarantee that you're getting a built-in PMC
-under the type id-less system is to look in the 'parrot' HLL, and even that
-isn't a total guarantee, because it could have been replaced in the 'parrot'
-HLL
-
-<pmichaud> the closest we have at the moment is
-
-  $P0 = get_root_namespace ['parrot'; 'Integer']
-  $P1 = new $P0
-
-but even this assumes that the 'Integer' namespace is tied to the Integer
-class, which also hasn't been specced
-
-<allison> builtin PMCs will be tied to a corresponding spot in the 'parrot' HLL
-namespace
-
-<pmichaud> according to pdd15: C<$P0 = new .Integer> can be replaced by C<$P0 =
-new 'Integer'> only in the parrot root namespace. in all other
-namespaces, one would need to get the namespace for the 'Integer' class and use
-that
-
-  $P0 = new 'Integer' # works in parrot HLL, root namespace
-  $P0 = new ['Integer'] # works in parrot HLL, any namespace
-
-<pmichaud> even easier, HLLs can set their notion of 'Integer' to point to the
-parrot class :-)
-
-<allison> yes, aliasing across namespaces is allowed
-
-=item *
-
-<particle> we can design a decoration for core pmcs with something that doesn't
-allow override in 'parrot' namespace, if it's wanted.
-
-<pmichaud> particle: I'm not sure it's entirely necessary to have the
-decoration i.e., I'd wait until we find we need it :-)
-
-<particle> sure, it's mostly a change for pmc2c i suspect
-
-  pmclass Foo does bar extends baz is_core {
-
-=item *
-
-ResizablePMCArray returns Undef for unset elements (so does the new object
-model, because it uses ResizablePMCArray for storage), but Hash returns null.
-Various other PMCs return different values for undefinedness.  Pick a standard.
-The current favorite is a singleton Null PMC. Check the implementation of
-PMCNULL.
-
-=item *
-
-<chromatic> How does COW work and why doesn't COW work? (docs/glossary.pod)
-
-=back
+=item - PMCs contain both state and behavior
 
-=head1 DESCRIPTION
+=item - PMCs can inherit from other PMCs
 
-=over 4
+=item - PMCs can be composed of low-level roles
 
 =item - High-level objects can subclass low-level PMCs
 
+
 =back
 
 =head1 IMPLEMENTATION
@@ -134,23 +48,15 @@
 All PMCs have the form:
 
     struct PMC {
-        pobj_t obj;
+        UnionVal cache;
+        Parrot_UInt flags;
         VTABLE *vtable;
         PMC *real_self;
- #if ! PMC_DATA_IN_EXT
         DPOINTER *data;
- #endif
         struct PMC_EXT *pmc_ext;
     };
 
-where C<obj> is a pointer to a C<pobj_t> structure:
-
-    typedef struct pobj_t {
-        UnionVal u;
-        Parrot_UInt flags;
-    } pobj_t;
-
-and where:
+where C<cache> is a pointer to a C<UnionVal> union:
 
     typedef union UnionVal {
         struct {
@@ -212,10 +118,7 @@
 C<pmc_ext> points to an extended PMC structure. This has the form:
 
     struct PMC_EXT {
- #if PMC_DATA_IN_EXT
-        DPOINTER *data;
- #endif
-        PMC *_metadata;             # [Note: replaced by roles]
+        PMC *_metadata;
         struct _Sync *_synchronize; # [Note: may be deprecated, see STM]
         PMC *_next_for_GC;
     };
@@ -238,10 +141,230 @@
 more) types of PMC, while particular Python datatypes will map onto different
 types of PMC.
 
-=head2 Interaction between PMCs and high-level objects
+=head2 Defining PMCs
+
+PMCs are declared by the C<pmclass> keyword:
+
+  pmclass <name> <modifiers> {
+  }
+
+The modifiers specify core features such as:
+
+=over 4
+
+=item need_ext
+
+Adds the C<PMC_EXT> structure when instantiating the PMC.
+
+=item abstract
+
+The PMC cannot be instantiated. (By convention, abstract classes are given
+lower-case names.)
+
+=item noinit
+
+Don't generate class initialization code (don't set up a vtable for the PMC).
+Used with C<abstract>.
+
+=item dynpmc
+
+The PMC is a dynamic PMC, so generate special class initialization code
+suitable for dynamic loading at runtime.
+
+=item singleton
+
+The PMC is a singleton, created in the constant PMC pool.
+
+=item no_ro
+
+Don't create a second read-only vtable for the PMC. (Used, for example,
+by STMs C<share_ro()>.)
+
+=item is_shared
+
+The PMC is shared (across threads).
+
+=item extends
+
+Inherit from another PMC. Takes one argument, the name of the PMC to inherit
+from.
+
+=item does
+
+Compose a role. Takes one argument, the name of the role to compose. [NOTE:
+this modifier has been taken from the older feature C<does> which is now called
+C<provides> (fulfills|supplies|satisfies).]
+
+=item provides
+
+The PMC satisfies a particular low-level interface, which gives some assurances
+on how and where a PMC can be used.
 
-{{ Address the problem of high-level objects inheriting from low-level PMCs,
-and any structural changes to low-level PMCs that might require. }}
+=over 4
+
+=item * C<array> is an aggregate PMC with numerically-keyed elements
+
+=item * C<hash> is an aggregate PMC with string-keyed elements
+
+=item * C<library> corresponds to a dynamic library
+
+=item * C<ref> references another PMC
+
+=item * C<string> behaves similarly to the base string type
+
+=item * C<integer> behaves similarly to the base int type
+
+=item * C<float> behaves similarly to the base number type
+
+=item * C<boolean> does true/false only.
+
+=item * C<scalar> (only used by the sample src/dynpmc/foo.pmc)
+
+=item * C<event> can be used with event queue
+
+=back
+
+=item hll
+
+Declare the PMC in an HLL namespace other than the default HLL 'parrot'.
+Takes one argument, the name of the HLL.
+
+=item maps
+
+Map the current PMC to a core PMC type for code declared in a particular
+HLL. May only be used together with the C<hll> modifier.
+
+=back
+
+=head3 Defining attributes
+
+The attributes of a PMC (both public and private) live in a custom
+struct for the PMC, stored in the C<data> member of the C<PMC> struct.
+The standard way of declaring attributes is with C<ATTR> within the body
+of a C<pmclass> or C<prole> declaration.
+
+  ATTR <type> <name> [:<modifier>];
+
+This declaration is used to generate the data struct for the PMC
+(named "Parrot_<pmcname>_Data"), including any attributes declared in a
+composed role.
+
+It's also possible to define and store the PMC's data struct manually,
+but the standard declaration syntax must be used in roles, in PMCs that
+compose roles, and in PMCs that will be subclassed by high-level
+classes.
+
+=head3 Defining vtable functions
+
+Vtable functions are defined as C functions within the body of the C<pmclass>
+declaration.
+
+  STRING *get_string() {...}
+  void set_string_native(STRING *value) {...}
+
+{{ PROPOSAL: I'd like to require that all vtable functions be declared
+with "VTABLE" at the beginning of the declaration, similar to "METHOD"
+and "PCCMETHOD". At the very least it's self-documentation. It might
+also be a useful hook for future pmc2c preprocessing. }}
+
+Within the body of vtable functions, several shortcuts are provided:
+
+=over 4
+
+=item INTERP
+
+The current interpreter object.
+
+=item SELF
+
+The current static invocant.
+
+=item DYNSELF
+
+The current dynamic invocant. [NOTE: it seems that this is actually what
+most people mean when they say C<SELF>.]
+
+=item SUPER
+
+Calls the current method in the nearest superclass, using the static
+type of C<SELF>. [NOTE: again, seems that this should be the dynamic
+type, not static type.]
+
+=item DYNSUPER
+
+Calls the current method in the nearest superclass, using the dynamic
+type of C<SELF>.
+
+=back
+
+=head3 Methods
+
+Methods are declared in the body of the C<pmclass> or C<prole>
+declaration with C<PCCMETHOD>.
+
+  PCCMETHOD inspect(STRING *what :optional, int got_what :opt_flag) {...}
+
+[NOTE: There is also an older C<METHOD> keyword, which is deprecated.]
+
+=head2 PMCs and Namespaces
+
+Like high-level classes, low-level PMCs are tied to a corresponding
+namespace. By default this is a namespace with the same name as the PMC
+in the 'parrot' HLL, but the C<hll> modifier in the C<pmclass>
+declaration selects a different HLL.
+
+Accessing a core PMC type from within an HLL other than 'parrot'
+requires the same steps as accessing a class from another HLL, first
+retrieving the namespace object, and then instantiating from that
+namespace.
+
+  $P0 = get_root_namespace ['parrot'; 'Integer']
+  $P1 = new $P0
+
+HLLs can choose to provide direct access to Parrot's core PMC types by
+aliasing them within the HLL namespace.
+
+=head2 Inheritance
+
+PMCs can inherit behavior and state from other PMCs. Inheritance is performed
+in the C<pmclass> declaration using the C<extends> keyword.
+
+  pmclass Foo extends Bar {
+  }
+
+=head2 Composition
+
+Composition is another form of code reuse in PMCs. Unlike inheritance, composed
+roles aren't complete stand-alone PMCs, they are just bundles of behavior and
+state that can be used within the composing PMC. As such, roles are never
+instantiated directly, and are never translated to C directly. They have no
+core structs, though they define attributes to be added to the PMC they are
+composed into. 
+
+When a PMC that uses a role is translated to C, the role provides vtable
+functions, methods, and attributes that will be added to the generated C code
+for that PMC. Composed vtable functions, methods, and attributes may not have
+the same name as corresponding features defined in the composing PMC. This is
+called a conflict, and must be explicitly resolved in the composing PMC. When
+composed features have the same name as inherited vtable functions, methods, or
+attributes, the composed feature overrides the inherited feature, just as it
+would if defined in the composing PMC.
+
+Roles are defined using the C<prole> keyword. 
+
+  prole <name> <modifiers> {
+  }
+
+Roles can compose other roles, but they can't inherit.
+
+Role attributes are defined using the same format as PMC attributes.
+
+Core roles live in src/pmc along with the core PMCs, but they have a file
+extension of C<.pr>.
+
+Roles are composed into a PMC with the C<does> modifier.
+
+=head2 Interaction between PMCs and high-level objects
 
 High-level objects, as specified in PDD15, need to be able to inherit from
 PMCs. This is achieved through the combination of a C<PMCProxy> PMC and
@@ -1382,6 +1505,11 @@
 Size-changing operations (such as push, pop, shift, unshift, and splice)
 on statically-sized arrays will throw an exception.
 
+ResizablePMCArray returns Undef for unset elements (so does the new
+object model, because it uses ResizablePMCArray for storage), but Hash
+returns PMCNULL. Standardize all core aggregate PMC types on the
+singleton PMCNULL.
+
 =over 4
 
 =item Array
@@ -1515,7 +1643,7 @@
 
 =head1 REFERENCES
 
-None.
+  docs/pmc2c.pod
 
 =cut
 

Reply via email to