lucy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mar...@apache.org
Subject svn commit: r805779 - in /lucene/lucy/trunk/boilerplater: lib/Boilerplater/Parser.pm lib/Boilerplater/Symbol.pm lib/Boilerplater/Variable.pm t/051-symbol.t t/300-variable.t
Date Wed, 19 Aug 2009 12:48:01 GMT
Author: marvin
Date: Wed Aug 19 12:48:01 2009
New Revision: 805779

URL: http://svn.apache.org/viewvc?rev=805779&view=rev
Log:
Commit LUCY-18, adding Boilerplater::Variable and moving more namespacing
information into the Boilerplater::Symbol abstract base class.

Added:
    lucene/lucy/trunk/boilerplater/lib/Boilerplater/Variable.pm   (with props)
    lucene/lucy/trunk/boilerplater/t/051-symbol.t   (with props)
    lucene/lucy/trunk/boilerplater/t/300-variable.t   (with props)
Modified:
    lucene/lucy/trunk/boilerplater/lib/Boilerplater/Parser.pm
    lucene/lucy/trunk/boilerplater/lib/Boilerplater/Symbol.pm

Modified: lucene/lucy/trunk/boilerplater/lib/Boilerplater/Parser.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/boilerplater/lib/Boilerplater/Parser.pm?rev=805779&r1=805778&r2=805779&view=diff
==============================================================================
--- lucene/lucy/trunk/boilerplater/lib/Boilerplater/Parser.pm (original)
+++ lucene/lucy/trunk/boilerplater/lib/Boilerplater/Parser.pm Wed Aug 19 12:48:01 2009
@@ -14,6 +14,7 @@
 use Boilerplater::Type::Arbitrary;
 use Boilerplater::Type::Object;
 use Boilerplater::Type::Composite;
+use Boilerplater::Variable;
 use Carp;
 
 our $grammar = <<'END_GRAMMAR';
@@ -38,6 +39,16 @@
     /([A-Z][A-Za-z0-9]+)(?!\w)/
     { $1 }
 
+var_declaration_statement:
+    exposure_specifier(?) variable_modifier(s?) type declarator ';'
+    {
+        $return = {
+            exposure  => $item[1][0] || 'parcel',
+            modifiers => $item[2],
+            declared  => Boilerplater::Parser->new_var( \%item, \%arg ),
+        };
+    }
+
 type:
       composite_type
     | simple_type
@@ -94,6 +105,16 @@
     | 'incremented'
     | 'decremented'
 
+exposure_specifier:
+      'public'
+    | 'private'
+    | 'parcel'
+    | 'local'
+
+variable_modifier:
+      'inert'
+    { $item[1] }
+
 primitive_type_specifier:
       chy_integer_specifier
     | c_integer_specifier 
@@ -121,6 +142,10 @@
 object_type_specifier:
     /[A-Z]+[A-Z0-9]*[a-z]+[A-Za-z0-9]*(?!\w)/
 
+declarator:
+    identifier 
+    { $item[1] }
+
 type_postfix:
       '*'
       { '*' }
@@ -129,10 +154,19 @@
     | '[' constant_expression ']'
       { "[$item[2]]" }
 
+identifier:
+    ...!reserved_word /[a-zA-Z_]\w*/x
+    { $item[2] }
+
 constant_expression:
       /\d+/
     | /[A-Z_]+/
 
+reserved_word:
+    /(char|const|double|enum|extern|float|int|long|register|signed|sizeof
+       |short|inert|struct|typedef|union|unsigned|void)(?!\w)/x
+    | chy_integer_specifier
+
 END_GRAMMAR
 
 sub new { return shift->SUPER::new($grammar) }
@@ -199,6 +233,22 @@
     return Boilerplater::Type::Composite->new(%args);
 }
 
+sub new_var {
+    my ( undef, $item, $arg ) = @_;
+    my $exposure = $item->{'exposure_specifier(?)'}[0];
+    my %args = $exposure ? ( exposure => $exposure ) : ();
+    if ($arg) {
+        $args{class_name}  = $arg->{class} if $arg->{class};
+        $args{class_cnick} = $arg->{cnick} if $arg->{cnick};
+    }
+    return Boilerplater::Variable->new(
+        parcel    => $parcel,
+        type      => $item->{type},
+        micro_sym => $item->{declarator},
+        %args,
+    );
+}
+
 sub new_parcel {
     my ( undef, $item ) = @_;
     Boilerplater::Parcel->singleton(

Modified: lucene/lucy/trunk/boilerplater/lib/Boilerplater/Symbol.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/boilerplater/lib/Boilerplater/Symbol.pm?rev=805779&r1=805778&r2=805779&view=diff
==============================================================================
--- lucene/lucy/trunk/boilerplater/lib/Boilerplater/Symbol.pm (original)
+++ lucene/lucy/trunk/boilerplater/lib/Boilerplater/Symbol.pm Wed Aug 19 12:48:01 2009
@@ -7,10 +7,15 @@
 use Carp;
 
 my %new_PARAMS = (
-    parcel   => undef,
-    exposure => undef,
+    parcel      => undef,
+    exposure    => undef,
+    class_name  => undef,
+    class_cnick => undef,
 );
 
+my $struct_regex     = qr/[A-Z]+[A-Z0-9]*[a-z]+[A-Za-z0-9]*/;
+my $class_name_regex = qr/^$struct_regex(::$struct_regex)*$/;
+
 sub new {
     my ( $either, %args ) = @_;
 
@@ -31,39 +36,46 @@
     my $self = bless { %new_PARAMS, %args, parcel => $parcel },
         ref($either) || $either;
 
-    # Validate the symbol's exposure, then cache accessor values.
+    # Validate exposure.
     confess("Invalid value for 'exposure': $self->{exposure}")
         unless $self->{exposure} =~ /^(?:public|parcel|private|local)$/;
-    $self->{_public}  = $self->{exposure} eq 'public'  ? 1 : 0;
-    $self->{_private} = $self->{exposure} eq 'private' ? 1 : 0;
-    $self->{_parcel}  = $self->{exposure} eq 'parcel'  ? 1 : 0;
-    $self->{_local}   = $self->{exposure} eq 'local'   ? 1 : 0;
+
+    # Validate class name, validate or derive class_cnick.
+    if ( defined $self->{class_name} ) {
+        confess("Invalid class name: $self->{class_name}")
+            unless $self->{class_name} =~ $class_name_regex;
+        if ( !defined $self->{class_cnick} ) {
+            $self->{class_name} =~ /(\w+)$/;
+            $self->{class_cnick} = $1;
+        }
+        confess("Invalid class_cnick: $self->{class_cnick}")
+            unless $self->{class_cnick} =~ /^[A-Z]+[A-Za-z0-9]*$/;
+    }
+    elsif ( defined $self->{class_cnick} ) {
+        # Sanity check class_cnick without class_name.
+        confess("Can't supply class_cnick without class_name");
+    }
 
     return $self;
 }
 
-sub set_parcel {
-    my ( $self, $parcel ) = @_;
-    if ( blessed($parcel) and $parcel->isa('Boilerplater::Parcel') ) {
-        $self->{parcel} = $parcel;
-    }
-    else {
-        $self->{parcel} = Boilerplater::Parcel->singleton( name => $parcel );
-    }
-}
-sub get_parcel { shift->{parcel} }
+sub get_parcel      { shift->{parcel} }
+sub get_class_name  { shift->{class_name} }
+sub get_class_cnick { shift->{class_cnick} }
 
 sub get_prefix { shift->{parcel}->get_prefix; }
 sub get_Prefix { shift->{parcel}->get_Prefix; }
 sub get_PREFIX { shift->{parcel}->get_PREFIX; }
 
-sub public  { shift->{_public} }
-sub private { shift->{_private} }
-sub parcel  { shift->{_parcel} }
-sub local   { shift->{_local} }
+sub public  { shift->{exposure} eq 'public' }
+sub private { shift->{exposure} eq 'private' }
+sub parcel  { shift->{exposure} eq 'parcel' }
+sub local   { shift->{exposure} eq 'local' }
 
 sub equals {
     my ( $self, $other ) = @_;
+    return 0 unless blessed($other);
+    return 0 unless $other->isa(__PACKAGE__);
     return 0 unless $self->{parcel}->equals( $other->{parcel} );
     if ( defined $self->{exposure} ) {
         return 0 unless defined $other->{exposure};
@@ -72,6 +84,13 @@
     else {
         return 0 if defined $other->{exposure};
     }
+    if ( defined $self->{class_name} ) {
+        return 0 unless defined $other->{class_name};
+        return 0 unless $self->{class_name} eq $other->{class_name};
+    }
+    else {
+        return 0 if defined $other->{class_name};
+    }
     return 1;
 }
 
@@ -94,29 +113,36 @@
 =head1 CONSTRUCTOR
 
     my $symbol = MySymbol->new(
-        parcel   => $parcel,      # required
-        exposure => $exposure,    # required
+        parcel      => $parcel,                             # default: special 
+        exposure    => $exposure,                           # required
+        class_name  => "Crustacean::Lobster::LobsterClaw",  # default: undef
+        class_cnick => "LobClaw",                           # default: special
     );
 
 =over
 
-=item
-
-B<parcel> - A Boilerplater::Parcel, or a string that can be used to
-create/retrieve one.
+=item * B<parcel> - A Boilerplater::Parcel, or a string that can be used to
+create/retrieve one.  If not supplied, will be assigned to the default Parcel.
 
-=item
+=item * B<exposure> - The scope in which the symbol is exposed.  Must be
+'public', 'parcel', 'private', or 'local'.
 
-B<exposure> - The scope in which the symbol is exposed.  Must be 'public',
-'parcel', 'private', or 'local'.
+=item * B<class_name> - A optional class name, consisting of one or more
+components separated by "::".  Each component must start with a capital
+letter, contain at least one lower-case letter, and consist entirely of the
+characters [A-Za-z0-9].
+
+=item * B<class_cnick> - The C nickname associated with the supplied class
+name.  If not supplied, will be derived if possible from C<class_name> by
+extracting the last class name component.
 
 =back
 
 =head1 OBJECT METHODS
 
-=head2 get_parcel set_parcel
+=head2 get_parcel get_class_name get_class_cnick
 
-Accessors for C<parcel> member var.
+Getters.
 
 =head2 get_prefix get_Prefix get_PREFIX
 

Added: lucene/lucy/trunk/boilerplater/lib/Boilerplater/Variable.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/boilerplater/lib/Boilerplater/Variable.pm?rev=805779&view=auto
==============================================================================
--- lucene/lucy/trunk/boilerplater/lib/Boilerplater/Variable.pm (added)
+++ lucene/lucy/trunk/boilerplater/lib/Boilerplater/Variable.pm Wed Aug 19 12:48:01 2009
@@ -0,0 +1,154 @@
+use strict;
+use warnings;
+
+package Boilerplater::Variable;
+use base qw( Boilerplater::Symbol );
+use Boilerplater::Type;
+use Boilerplater::Util qw( verify_args );
+use Carp;
+
+our %new_PARAMS = (
+    type        => undef,
+    micro_sym   => undef,
+    parcel      => undef,
+    exposure    => 'local',
+    class_name  => undef,
+    class_cnick => undef,
+);
+
+sub new {
+    my $either = shift;
+    verify_args( \%new_PARAMS, @_ ) or confess $@;
+    my $self = $either->SUPER::new( %new_PARAMS, @_ );
+    confess "micro_sym is required" unless $self->{micro_sym};
+    confess "invalid type"
+        unless ref( $self->{type} )
+            && $self->{type}->isa("Boilerplater::Type");
+    return $self;
+}
+
+sub get_type  { shift->{type} }
+sub micro_sym { shift->{micro_sym} }
+
+sub equals {
+    my ( $self, $other ) = @_;
+    return 0 unless $self->{micro_sym} eq $other->{micro_sym};
+    return 0 unless $self->{type}->equals( $other->{type} );
+    return $self->SUPER::equals($other);
+}
+
+sub local_c {
+    my $self      = shift;
+    my $type      = $self->{type};
+    my $array_str = '';
+    if ( $type->is_composite ) {
+        $array_str = $type->get_array || '';
+    }
+    my $type_str = $array_str ? $type->to_c : $type->to_c;
+    return "$type_str $self->{micro_sym}$array_str";
+}
+
+sub global_c {
+    my $self = shift;
+    my $type = $self->{type};
+    my $name = $self->get_prefix . "$self->{class_cnick}_$self->{micro_sym}";
+    my $postfix = '';
+    if ( $type->is_composite ) {
+        $postfix = $type->get_array || '';
+    }
+    return $type->to_c . " $name$postfix";
+}
+
+sub local_declaration { return shift->local_c . ';' }
+
+1;
+
+__END__
+
+__POD__
+
+=head1 NAME
+
+Boilerplater::Variable - A Boilerplater variable.
+
+=head1 DESCRIPTION
+
+A variable, having a L<Type|Boilerplater::Type>, a micro_sym (i.e. name), an
+exposure, and optionally, a location in the global namespace hierarchy.
+
+Variable objects which exist only within a local scope, e.g. those within
+parameter lists, do not need to know about class.  In contrast, inert class
+vars, for example, need to know class information so that they can declare
+themselves properly.
+
+=head1 METHODS
+
+=head2 new
+
+    my $var = Boilerplater::Variable->new(
+        parcel      => 'Boil',
+        type        => $type,    # required
+        micro_sym   => 'foo',    # required
+        exposure    => undef,    # default: 'local'
+        class_name  => "Foo",    # default: undef
+        class_cnick => "Foo",    # default: undef
+    );
+
+=over
+
+=item * B<type> - A L<Boilerplater::Type>.
+
+=item * B<micro_sym> - The variable's name, without any namespacing prefixes.
+
+=item * B<exposure> - See L<Boilerplater::Symbol>.
+
+=item * B<class_name> - See L<Boilerplater::Symbol>.
+
+=item * B<class_cnick> - See L<Boilerplater::Symbol>.
+
+=back
+
+=head2 local_c
+
+    # e.g. "boil_Foo *foo"
+    print $variable->local_c;
+
+Returns a string with the Variable's C type and its C<micro_sym>.
+
+=head2 global_c
+
+    # e.g. "boil_Foo *boil_Foo_foo"
+    print $variable->global_c;
+
+Returns a string with the Variable's C type and its fully qualified name
+within the global namespace.
+
+=head2 local_declaration
+
+    # e.g. "boil_Foo *foo;"
+    print $variable->local_declaration;
+
+Returns C code appropriate for declaring the variable in a local scope, such
+as within a C parameter list or struct definition, or as an automatic variable
+within a C function.  
+
+=head1 COPYRIGHT AND LICENSE
+
+    /**
+     * Copyright 2009 The Apache Software Foundation
+     *
+     * Licensed under the Apache License, Version 2.0 (the "License");
+     * you may not use this file except in compliance with the License.
+     * You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+     * implied.  See the License for the specific language governing
+     * permissions and limitations under the License.
+     */
+
+=cut
+

Propchange: lucene/lucy/trunk/boilerplater/lib/Boilerplater/Variable.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/boilerplater/t/051-symbol.t
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/boilerplater/t/051-symbol.t?rev=805779&view=auto
==============================================================================
--- lucene/lucy/trunk/boilerplater/t/051-symbol.t (added)
+++ lucene/lucy/trunk/boilerplater/t/051-symbol.t Wed Aug 19 12:48:01 2009
@@ -0,0 +1,49 @@
+use strict;
+use warnings;
+
+use Test::More tests => 37;
+
+package BoilingThing;
+use base qw( Boilerplater::Symbol );
+
+sub new { return shift->SUPER::new( exposure => 'parcel', @_ ) }
+
+package main;
+
+for (qw( foo FOO 1Foo Foo_Bar FOOBAR 1FOOBAR )) {
+    eval { my $thing = BoilingThing->new( class_name => $_ ) };
+    like( $@, qr/class name/, "Reject invalid class name $_" );
+    my $bogus_middle = "Foo::" . $_ . "::Bar";
+    eval { my $thing = BoilingThing->new( class_name => $bogus_middle ) };
+    like( $@, qr/class name/, "Reject invalid class name $bogus_middle" );
+}
+
+my @exposures = qw( public private parcel local );
+for my $exposure (@exposures) {
+    my $thing = BoilingThing->new( exposure => $exposure );
+    ok( $thing->$exposure, "exposure $exposure" );
+    my @not_exposures = grep { $_ ne $exposure } @exposures;
+    ok( !$thing->$_, "$exposure means not $_" ) for @not_exposures;
+}
+
+my $foo    = BoilingThing->new( class_name => 'Foo' );
+my $foo_jr = BoilingThing->new( class_name => 'Foo::FooJr' );
+ok( !$foo->equals($foo_jr), "different class_name spoils equals" );
+is( $foo_jr->get_class_name, "Foo::FooJr", "get_class_name" );
+is( $foo_jr->get_class_cnick, "FooJr", "derive class_cnick from class_name" );
+
+my $public_exposure = BoilingThing->new( exposure => 'public' );
+my $parcel_exposure = BoilingThing->new( exposure => 'parcel' );
+ok( !$public_exposure->equals($parcel_exposure),
+    "different exposure spoils equals"
+);
+
+my $lucifer_parcel = Boilerplater::Parcel->singleton( name => 'Lucifer' );
+my $lucifer = BoilingThing->new( parcel => 'Lucifer' );
+ok( $lucifer_parcel == $lucifer->get_parcel, "derive parcel" );
+is( $lucifer->get_prefix, "lucifer_", "get_prefix" );
+is( $lucifer->get_Prefix, "Lucifer_", "get_Prefix" );
+is( $lucifer->get_PREFIX, "LUCIFER_", "get_PREFIX" );
+my $luser = BoilingThing->new( parcel => 'Luser' );
+ok( !$lucifer->equals($luser), "different parcel spoils equals" );
+

Propchange: lucene/lucy/trunk/boilerplater/t/051-symbol.t
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/boilerplater/t/300-variable.t
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/boilerplater/t/300-variable.t?rev=805779&view=auto
==============================================================================
--- lucene/lucy/trunk/boilerplater/t/300-variable.t (added)
+++ lucene/lucy/trunk/boilerplater/t/300-variable.t Wed Aug 19 12:48:01 2009
@@ -0,0 +1,61 @@
+use strict;
+use warnings;
+
+use Test::More tests => 13;
+use Boilerplater::Type;
+use Boilerplater::Parser;
+
+BEGIN { use_ok('Boilerplater::Variable') }
+
+my $parser = Boilerplater::Parser->new;
+$parser->parcel_definition('parcel Boil;')
+    or die "failed to process parcel_definition";
+
+sub new_type { $parser->type(shift) }
+
+eval {
+    my $death = Boilerplater::Variable->new(
+        micro_sym => 'foo',
+        type      => new_type('int'),
+        extra_arg => undef,
+    );
+};
+like( $@, qr/extra_arg/, "Extra arg kills constructor" );
+
+eval { my $death = Boilerplater::Variable->new( micro_sym => 'foo' ) };
+like( $@, qr/type/, "type is required" );
+eval { my $death = Boilerplater::Variable->new( type => new_type('i32_t') ) };
+like( $@, qr/micro_sym/, "micro_sym is required" );
+
+my $var = Boilerplater::Variable->new(
+    micro_sym => 'foo',
+    type      => new_type('float*')
+);
+is( $var->local_c,           'float* foo',  "local_c" );
+is( $var->local_declaration, 'float* foo;', "declaration" );
+ok( $var->local, "default to local access" );
+
+$var = Boilerplater::Variable->new(
+    micro_sym => 'foo',
+    type      => new_type('float[1]')
+);
+is( $var->local_c, 'float foo[1]',
+    "to_c appends array to var name rather than type specifier" );
+
+$var = Boilerplater::Variable->new(
+    parcel      => 'Boil',
+    micro_sym   => 'foo',
+    type        => new_type("Foo*"),
+    class_name  => 'Crustacean::Lobster::LobsterClaw',
+    class_cnick => 'LobClaw',
+);
+is( $var->global_c, 'boil_Foo* boil_LobClaw_foo', "global_c" );
+
+isa_ok( $parser->var_declaration_statement($_)->{declared},
+    "Boilerplater::Variable", "var_declaration_statement: $_" )
+    for (
+    'parcel int foo;',
+    'private Obj *obj;',
+    'public inert i32_t **foo;',
+    'Dog *fido;'
+    );

Propchange: lucene/lucy/trunk/boilerplater/t/300-variable.t
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message