use strict; use warnings; package Clownfish::Type; use Clownfish::Parcel; use Clownfish::Util qw( verify_args ); use Scalar::Util qw( blessed ); use Carp; our %new_PARAMS = ( const => undef, specifier => undef, indirection => undef, parcel => undef, c_string => undef, ); sub new { my $either = shift; my $package = ref($either) || $either; confess( __PACKAGE__ . "is an abstract class" ) if $package eq __PACKAGE__; verify_args( \%new_PARAMS, @_ ) or confess $@; my $self = bless { %new_PARAMS, @_, }, $package; if ( defined $self->{parcel} ) { if ( !blessed( $self->{parcel} ) ) { $self->{parcel} = Clownfish::Parcel->singleton( name => $self->{parcel} ); } confess("Not a Clownfish::Parcel") unless $self->{parcel}->isa('Clownfish::Parcel'); } return $self; } sub get_specifier { shift->{specifier} } sub get_parcel { shift->{parcel} } sub const { shift->{const} } sub nullable { shift->{nullable} } sub is_object {0} sub is_primitive {0} sub is_integer {0} sub is_floating {0} sub is_void {0} sub is_composite {0} sub is_string_type {0} sub equals { my ( $self, $other ) = @_; return 0 unless blessed($other); return 0 unless $other->isa(__PACKAGE__); return 1; } sub to_c { shift->{c_string} } sub set_c_string { $_[0]->{c_string} = $_[1] } 1; __END__ __POD__ =head1 NAME Clownfish::Type - A variable's type. =head1 METHODS =head2 new my $type = MyType->new( specifier => 'char', # default undef indirection => undef, # default 0 const => 1, # default undef parcel => undef, # default undef c_string => undef, # default undef ); Abstract constructor. =over =item * B - The C name for the type, not including any indirection or array subscripts. =item * B - integer indicating level of indirection. Example: the C type "float**" has a specifier of "float" and indirection 2. =item * B - should be true if the type is const. =item * B - A Clownfish::Parcel or a parcel name. =item * B - The C representation of the type. =back =head2 equals do_stuff() if $type->equals($other); Returns true if two Clownfish::Type objects are equivalent. The default implementation merely checks that C<$other> is a Clownfish::Type object, so it should be overridden in all subclasses. =head2 to_c # Declare variable "foo". print $type->to_c . " foo;\n"; Return the C representation of the type. =head2 set_c_string Set the C representation of the type. =head2 get_specifier get_parcel const nullable Accessors. =head2 is_object is_primitive is_integer is_floating is_composite is_void do_stuff() if $type->is_object; Shorthand for various $type->isa($package) calls. =over =item * is_object: Clownfish::Type::Object =item * is_primitive: Clownfish::Type::Primitive =item * is_integer: Clownfish::Type::Integer =item * is_floating: Clownfish::Type::Float =item * is_void: Clownfish::Type::Void =item * is_composite: Clownfish::Type::Composite =back =head2 is_string_type Returns true if $type represents a Clownfish type which holds unicode strings. =head1 COPYRIGHT AND LICENSE Copyright 2008-2010 Marvin Humphrey This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut