Class-CompiledC

 view release on metacpan or  search on metacpan

lib/Class/CompiledC.pm  view on Meta::CPAN

package Class::CompiledC;

=head1 NAME

Class::CompiledC

=cut

use 5.008007;
use strict;
use warnings;
use Carp;
use base     qw/Attribute::Handlers/;
use Inline;
use Exporter qw/import/;

=head1 VERSION

This document describes version 2.21 of Class::CompiledC,
released Fri Oct 27 23:28:06 CEST 2006 @936 /Internet Time/

=cut

our $VERSION = 2.21;
our %includes;
our %funcs;
our %extfuncs;
our %code;
our %scheduled;
our %types;
our %EXPORT_TAGS;
our @EXPORT_OK;
our $re_ft;
our $re_ft_isa;

sub __circumPrint($$$);
sub __include;
sub __baseref($$);
sub __hashref($);
sub __arrayref($);
sub __coderef($);
sub __fetchSymbolName($);
sub __promoteFieldTypeToMacro($);
sub __parseFieldType;


$re_ft     = qr/^(?:\s*)(int|float|number|string|ref|arrayref|hashref|
                         coderef|object|regexpref|any|uint)(?:\s*)/xi;

$re_ft_isa = qr/^(?:\s*)isa(?:\s*)\((?:\s*)([\w:]*)(?:\s*)\)(?:\s*)/i;

=head1 ABSTRACT

Class::CompiledC -- use C structs for your objects.

=head1 SYNOPSIS

  package Foo;
  use strict;
  use warnings;

  use base qw/Class::CompiledC/;

  sub type     : Field(String);
  sub data     : Field(Hashref);
  sub count    : Field(Int);
  sub callback : Field(Coderef);
  sub size     : Field(Float);
  sub dontcare : Field(Number);
  sub dumper   : Field(Isa(Data::Dumper));
  sub items    : Field(Arrayref);
  sub notsure  : Field(Object);

  my $x;

  $x = Foo->new(-type     => "example",
                -data     => {},
                -count    => 0,
                -callback => sub { print "j p " ^ " a h " ^ " " x 4 while 1},
                -size     => 138.4,
                -dontcare => 12,
                -dumper   => Data::Dumper->new,
                -items    => [qw/coffee cigarettes beer/],
                -notsure  => SomeClass->new
                );




=head1 DESCRIPTION

Note: Documentation is incomplete, partly outdated, of poor style and full of
typos. I need a ghostwriter.

Class::CompiledC creates classes which are based on C structs, it does this by
generating C code and compiling the code when your module is compiled (1). You
can add constraints on the type of the data that can be stored in the instance
variables of your objects by specifiying a C<field type> (i call instance
variables fields because it's shorter). A field without constraints are declared
by using the C<: Field> attribute (2) on a subroutine stub (3) of the name you
would like to have for your field eg. C<sub Foo : Field;> this would generate a
field called 'foo' and it's accesor method, also called 'foo' If you want to add
a constraint to the field just name the type as a parameter for the attribute eg

lib/Class/CompiledC.pm  view on Meta::CPAN

{
        __baseref $_[0], 'HASH';
}

=head3 __arrayref

  __arrayref REFERENCE
  Type: Subroutine.
  Export: on request.
  Prototype: $

Determines if REFERENCE is actually a array reference.
Utitlizes C<__baseref>.

=cut

sub __arrayref($)
{
        __baseref $_[0], 'ARRAY';
}

=head3 __coderef

  __coderef REFERENCE
  Type: Subroutine.
  Export: on request.
  Prototype: $

Determines if REFERENCE is actually a code reference.
Utitlizes C<__baseref>.

=cut

sub __coderef($)
{
        __baseref($_[0], 'CODE')
}

=head3 __fetchSymbolName

  __fetchSymbolName GLOBREF
  Type: Subroutine.
  Export: on request.
  Prototype: $

Returns the Symbol name from the glob reference GLOBREF.
Croaks if GLOBREF acutally isn't a glob reference.

=cut

sub __fetchSymbolName($)
{
        no strict 'refs';
        my $symbol = shift;

        __baseref $symbol, 'GLOB' or croak 'not a GLOB reference';

        return *$symbol{NAME};
}

=head3 __promoteFieldTypeToMacro

  __promoteFieldTypeToMacro FIELDTYPE
  Type: Subroutine.
  Export: on request.
  Prototype: none

Takes a fieldtype specfication, and returns a C<C> macro for doing the test.
Does not handle parametric types like C<isa>. See C<__parseFieldType> for that.

=cut

sub __promoteFieldTypeToMacro($)
{
        my $type = shift;

        return '' unless ($type);
        return '' if     ($type =~ /^any$/i);
        return sprintf '__CHECK(__IS%s(__ARG0), "%s")', uc $type, $type;
}

=head3 __parseFieldType

  __parseFieldType FIELDTYPE
  Type: Subroutine.
  Export: on request.
  Prototype: none

Takes a fieldtype specfication, and returns a C<C> macro for doing the test.
Handles all field types. Delegates most work to the C<__promoteFieldTypeToMacro>
subroutine.

=cut

sub __parseFieldType
{
      local $_ = shift;

      if (/$re_ft/)
      {
             # warn sprintf "yeah %s !", __promoteFieldTypeToMacro $1;
              return __promoteFieldTypeToMacro($1);
      }
      elsif (/$re_ft_isa/)
      {
              croak "fail0r: isa type needs a classname argument\n" unless $1;
              return '__CHECK(__ISA(__ARG0, '."\"$1\"), \"__ISA\")";

      }
      else
      {
              croak "fail0r: bad type specified $_\n";
      }

}


=head3 Include

  sub Foo : C(...)     Include(<math.h>)
  sub Foo : Field(...) Include("bar.h")

  Type: Attribute Handler
  Export: no.

=cut

sub Include : ATTR(CODE, BEGIN)
{
        my $package;
        my $symbol;
        my $ref;
        my $attribute;
        my $data;

        $package    = shift || croak "no package supplied";
        $symbol     = shift || croak "no symbol supplied";
        $ref        = shift || croak "no reference supplied";
        $attribute  = shift || croak "no attribute supplied";
        $data       = shift || croak "no includes supplied";

        $data               = [ $data ] unless __arrayref $includes{$package};
        $includes{$package} = []        unless __arrayref $data;

        push @{$includes{$package}}, @{$data};
}

=head3 C

  sub Foo : C(RETVAL, ARG0, ...)

  Type: Attribute Handler
  Export: no.

=cut

sub C       : ATTR(CODE, CHECK, RAWDATA)
{
        my $package;
        my $symbol;
        my $attribute;
        my $data;

lib/Class/CompiledC.pm  view on Meta::CPAN


        $data ? eval "use $data" : eval "use ${package}::Method::${name}";
        bless *{$symbol}{CODE}, ($data || "${package}::Method::${name}");

        return;
}

=head2 Inheritance

Class::CompiledC inherits the following methods from it's ancestors

=over

=item methods inherited from C<Attribute::Handlers>

=over

=item C<import>

=item C<_resolve_lastattr>

=item C<DESTROY>

=item C<_gen_handler_AH_>

=item C<_apply_handler_AH_>

=back

=back

=head2 Export

Class::CompiledC does not export anything by default but has a number of subroutines
to Export on request.

=head2 Export Tags

Class::CompiledC defines the following export tags:

=over

=item ref Subroutines to verify the type of references

=item misc miscellanous subroutines

=item field specification subroutines

=item intern miscellanous subroutines with low value outside this package

=item all Everything.

=back

=cut

BEGIN
{
        $EXPORT_TAGS{ref}    = [qw/__arrayref  __coderef __hashref/];
        $EXPORT_TAGS{misc}   = [qw/__fetchSymbolName __baseref __circumPrint/];
        $EXPORT_TAGS{field}  = [qw/__parseFieldType __promoteFieldTypeToMacro/];
        $EXPORT_TAGS{intern} = [qw/__include/];
        $EXPORT_TAGS{all}    = [map {@{$_}} values %EXPORT_TAGS ];
}

=head2 Exportable Symbols

The following subroutines are (im|ex)portable, either explicitly by name or
as part of a tag.

=over

=item C<__include>

=item C<__arrayref>

=item C<__coderef>

=item C<__hashref>

=item C<__fetchSymbolName>

=item C<__baseref>

=item C<__circumPrint>

=item C<__parseFieldType>

=item C<__promoteFieldTypeToMacro>

=back

=cut

BEGIN
{
        @EXPORT_OK = @{$EXPORT_TAGS{all}};
}

=head1 EXAMPLES

  TODO

=head1 DIAGNOSTICS

=over

=item C<no package supplied>

this message is usually caused by an class method called as a subroutine.
I<fatal error>

=item C<no target package supplied>

Some methods (and subroutines, btw) need a target package to operate on,
it seems that the argument is missing, or has evaluated to false value, which
very unlikely to be valid.
I<fatal error>

=item C<no code supplied>

This message is is caused by the __addCode method, which renders useless
without a supplied code argument.
I<fatal error>

=item C<no type supplied>

This message is caused by the __addCode method, when called without a type
argument. The __addCode method can only operate with a valid type argument.
Currently valid types are C<base> and C<ext> but more may be added in future.
I<fatal error>


=item C<bad type supplied>

This message is caused by the __addCode method, when called with a invalid type
argument. Currently valid types are C<base> and C<ext>
but more may be added in future.
I<fatal error>

=item C<fail0r: isa type needs a classname argument>

This message is caused by the __parseFieldType subroutine. The __parseFieldType
subroutine (which gets called by the Field attribute handler) found C<isa> as
type but without a classname. A is a check doesn't make sense without a
classname. If you just want to make sure that it is a object, you may use
C<Isa(Universal)> or (generally faster and shorter) C<Object>.
I<fatal error>

lib/Class/CompiledC.pm  view on Meta::CPAN

=item *serious code cleanup

I still find too much things that are done the fast way instead of the right
way, this really bothers me.

=item *outsourcing

A few things need to be outsourced right away. I just don't know where to put
them. Especially the stuff not related to classes should be placed somewhere
else. The utility __.* subs (not methods!) could be placed in a different
package and locally (or maybe lexically?) imported, to avoid namespace pollution
of subclasses.

Random thought: lexical importing ? what a cute idea! is this possible?


=back

=head1 SEE ALSO

=over

=item TODO

=back

=head1 AUTHOR

blackhat.blade
 The Hive

blade@focusline.de

=head1 COPYRIGHT

                          Copyright (c) 2005, 2006
              blackhat.blade The Hive.  All Rights Reserved.
       This module is free software. It may be used, redistributed
           and/or modified under the terms of the Artistic license.

=cut

1;

__END__
2.14 Wed Jan 18 00:44:39 CET 2006 @31 /Internet Time/
     everything till here...
2.15 Thu Jan 19 20:28:41 CET 2006 @853 /Internet Time/
     fixed documentation issues, the Field type for regular exprssions
     is C<Regexpref> and I<not> C<Regexref>. I also had Regexenref in mind...
2.16 Sun Oct 08 00:05:19 CEST 2006 @962 /Internet Time/
     fixed (?:Array|Code|Hash)ref type checking code
2.17 Sat Oct 21 01:01:45 CEST 2006 @1 /Internet Time/
     added a few sanity checks for __fetchSymbolName
2.18 Sun Oct 22 13:21:16 CEST 2006 @514 /Internet Time/
     fixed some serious bugs concerning refcounts of non ref values
     fixed (?:Array|Code|Hash)ref type checking code
2.19 Sun Oct 22 19:52:04 CEST 2006 @786 /Internet Time/
     relocated field type parsing into __genBaseCode in anticipation to support
       introspection
     refactored __promoteFieldTypeToMacro sub
     adapted __addParentFields to emit only valid field types
     added inspect method, it returns a hashref with fieldnames as keys and
      field types as values. (you may change that hash but don't expect any
      changes to persist, or even to propagate back and change the class on the
      fly, we are not at this point, and we're not going into this directon)
2.20 Thu Oct 26 21:48:22 CEST 2006 @866 /Internet Time/
     first public release
     renamed to Class::CompiledC to avoid the creation of a new root namespace
     added version requirement for 5.8.7, sorry for this but I cannot tell if
     it will run with earlier versions.
2.21 Fri Oct 27 23:27:38 CEST 2006 @935 /Internet Time/
     no code changes, fixed errors in Makefile.pl
2.22 Sun Oct 29 22:52:42 CET 2006 @953 /Internet Time/
     updated documentation,
     minor code cleanups.



( run in 0.500 second using v1.01-cache-2.11-cpan-e1769b4cff6 )