—=head1 NAME
ExtUtils::XSpp::Plugin - XS++ plugin interface
=head1 DESCRIPTION
The XS++ plugin interface is B<EXPERIMENTAL> and subject to change.
If you still want to use it, read the source of this module.
=begin internal
=head1 SYNTAX
%loadplugin{MyPlugin};
int foo(int y) %FuncTag{Foo};
class klass
{
%ClassTag{Klass};
void bar() %MethodTag{Bar};
};
There are two ways a plugin can modify the code emitted by XS++: it
can run after the parsing completes and modify the expression tree
before it is emitted or it can handle custom annotation tags
associated with a class/function/method.
A custom tag can have either positional or named parameters:
# positional
%Foo{Id}{% multi
line
block %}{AnotherId};
# named
%Bar{
%AParam{Id};
%AnotherParam{% block %};
%AThirdParam{AnotherId};
};
No check is performed on parameter names/types/count. The parser only
gives an error if the annotation is not handled by any plugin.
Positional parameters are passed to tag handlers as an array reference
in the C<any_named_arguments> parameter; named handlers are passed as
an hash reference in the C<any_positional_arguments> parameter.
The value of a special block parameter is an array reference with an
element for each line in the special block. For consistency, the
value of an identifier parameter is a single-element array reference.
=head1 XS++ METHODS
These methods are defined in the parser object.
=head2 add_post_process_plugin
$parser->add_post_process_plugin( plugin => $instance );
Registers a post-processing plugin to be called after the parsing
finishes.
=head2 add_function_tag_plugin
$parser->add_function_tag_plugin( plugin => $instance,
# optional
tag => $tag,
);
Add a plugin to handle functions annotated with tags.
=head2 add_class_tag_plugin
$parser->add_class_tag_plugin( plugin => $instance,
# optional
tag => $tag,
);
Add a plugin to handle classes annotated with tags.
=head2 add_method_tag_plugin
$parser->add_method_tag_plugin( plugin => $instance,
# optional
tag => $tag,
);
Add a plugin to handle methods annotated with tags.
=head2 add_toplevel_tag_plugin
$parser->add_toplevel_tag_plugin( plugin => $instance,
# optional
tag => $tag,
);
Add a plugin to handle top-level directives.
=head1 PLUGIN METHODS
These methods can be defined by the plugin to modify the emitted code.
=head2 register_plugin
sub register_plugin {
my( $class, $parser ) = @_;
# call the various add_*_plugin methods to register the plugin
}
This method is called once for each loaded plugin, the first time the
parses sees the C<%load_plugin> directive.
TODO add another method that is called once for each C<%loadplugin>
declaration, and allow passing parameters to the plugin.
=head2 post_process
sub post_process {
my( $self, $nodes ) = @_;
# process and mutate the list of nodes
}
=head2 handle_function_tag
sub handle_function_tag {
my( $self, $function, $tag, %args ) = @_;
# do something useful
}
C<$function> is a C<Function> node. C<$tag> is the tag string,
without the C<%> prefix. C<%args> are the arguments passed to the
tag.
If the method handles the tag, it must return C<1> to the caller.
=head2 handle_class_tag
sub handle_class_tag {
my( $self, $class, $tag, %args ) = @_;
# do something useful
}
C<$class> is a C<Class> node. C<$tag> is the tag string, without the
C<%> prefix. C<%args> are the arguments passed to the tag. The
handler for the class is called after the handlers for its methods.
If the method handles the tag, it must return C<1> to the caller.
=head2 handle_method_tag
sub handle_method_tag {
my( $self, $method, $tag, %args ) = @_;
# do something useful
}
C<$method> is a C<Method> node. C<$tag> is the tag string, without
the C<%> prefix. C<%args> are the arguments passed to the tag.
If the method handles the tag, it must return C<1> to the caller.
=head2 handle_toplevel_tag
sub handle_toplevel_tag {
my( $self, undef, $tag, %args ) = @_;
# do something useful
}
C<$tag> is the tag string, without the C<%> prefix. C<%args> are the
arguments passed to the tag. The C<undef> value is for uniformity
with other tag handlers.
If the method handles the tag, it must return C<1> to the caller.
=end internal
=cut