Skip to content

Commit 1cce200

Browse files
committed
Flesh out EXPORTHOW specification a bit.
Provide for safe compositional use of meta-objects as well as custom package declarators. Also spec that compilers should complain about trying to import two different replacement meta-objects for the same declarator in a single scope.
1 parent 8f30d2d commit 1cce200

File tree

1 file changed

+56
-8
lines changed

1 file changed

+56
-8
lines changed

S12-objects.pod

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,15 +2528,63 @@ When the parser encounters a package declarator, it uses the name of
25282528
the declarator (such as C<class> or C<grammar>) to look up the type of
25292529
meta-object to use. The default meta-objects support the standard Perl 6
25302530
OO semantics. However, it is possible for a module to export different
2531-
meta-objects with different semantics. This is done by making entries in
2532-
an EXPORTHOW package, which in turn must be located in UNIT of the module.
2533-
The name it is installed under maps to a package or type declarator name.
2534-
2535-
Thus, a module can provide a replacement implementation of the meta-object
2536-
type used for grammars like this:
2531+
meta-objects with different semantics. This is done by declaring an
2532+
C<EXPORTHOW> package, which should be located in C<UNIT> of the module
2533+
(and thus can be lexically scoped).
2534+
2535+
Just as the C<EXPORT> package never contains symbols directly, but instead
2536+
contains packages that denote tags and directives (such as C<DEFAULT>), the
2537+
C<EXPORTHOW> package expects meta-objects to be installed under one of the
2538+
following packages:
2539+
2540+
SUPERSEDE Uses the exported meta-object for the named declarator in
2541+
the scope that the module is imported in to
2542+
COMPOSE Takes the meta-object currently in effect for the named
2543+
declarator and composes the exported role into it
2544+
DECLARE Like SUPERSEDE, but also adds a new package declarator to
2545+
the grammar if required
2546+
2547+
For example, a module can replace the meta-object used for the C<grammar>
2548+
keyword in any scope it is imported into by doing:
2549+
2550+
my module EXPORTHOW::SUPERSEDE { }
2551+
EXPORTHOW::SUPERSEDE<grammar> = TracedGrammarHOW;
2552+
2553+
An MVC framework could declare a new C<controller> package declarator and
2554+
associate it with a meta-class of its choosing by doing:
2555+
2556+
my module EXPORTHOW::DECLARE { }
2557+
EXPORTHOW::DECLARE<controller> = ControllerHOW;
2558+
2559+
The C<COMPOSE> directive is perhaps the most sophisticated, and its usage is
2560+
encouraged where possible. Instead of exporting an entirely new meta-object,
2561+
C<COMPOSE> enables exporting a role. At the point the declarator is first used,
2562+
all roles exported for it through C<COMPOSE> will be taken together and added
2563+
to a class derived from the current meta-object for the declarator (which may
2564+
have been provided by a SUPERSEDE or DECLARE export from another module used in
2565+
the scope). This class will then be composed, with any conflicts indicated.
2566+
2567+
my module EXPORTHOW::COMPOSE {
2568+
# Provide a role that adds logging to class method calls.
2569+
role class {
2570+
method find_method($obj, $name) {
2571+
say "Calling $name";
2572+
nextsame;
2573+
}
2574+
2575+
method publish_method_cache($obj) {
2576+
# Make sure all dispatches go through find_method
2577+
}
2578+
}
2579+
}
25372580

2538-
my module EXPORTHOW { }
2539-
EXPORTHOW::<grammar> = TracedGrammarHOW;
2581+
The benefit of C<COMPOSE> is that it enables two modules that extend a meta-object
2582+
in a non-conflicting way to be used together in the same scope, with explicit
2583+
detection of conflicts if they occur. For example, if one module wishes to
2584+
override C<compose> and another wishes to override C<find_method>, the two can
2585+
be used together safely. By contrast, C<SUPERSEDE> and C<DECLARE> can only be used
2586+
by one module per declarator in a given scope, thwarting composition. The
2587+
compiler should produce an error if this rule is broken.
25402588

25412589
The easiest way to define a new meta-object is to inherit from an existing
25422590
meta-object.

0 commit comments

Comments
 (0)