add TODO test
[gitmo/Package-Stash-XS.git] / lib / Stash / Manip.pm
index 38177c7..40e9567 100644 (file)
@@ -24,6 +24,9 @@ Manipulating stashes (Perl's symbol tables) is occasionally necessary, but
 incredibly messy, and easy to get wrong. This module hides all of that behind a
 simple API.
 
+NOTE: Most methods in this class require a variable specification that includes
+a sigil. If this sigil is absent, it is assumed to represent the IO slot.
+
 =head1 METHODS
 
 =cut
@@ -75,23 +78,23 @@ sub namespace {
         '@' => 'ARRAY',
         '%' => 'HASH',
         '&' => 'CODE',
+        ''  => 'IO',
     );
 
     sub _deconstruct_variable_name {
         my ($self, $variable) = @_;
 
-        (defined $variable)
+        (defined $variable && length $variable)
             || confess "You must pass a variable name";
 
         my $sigil = substr($variable, 0, 1, '');
 
-        (defined $sigil)
-            || confess "The variable name must include a sigil";
-
-        (exists $SIGIL_MAP{$sigil})
-            || confess "I do not recognize that sigil '$sigil'";
-
-        return ($variable, $sigil, $SIGIL_MAP{$sigil});
+        if (exists $SIGIL_MAP{$sigil}) {
+            return ($variable, $sigil, $SIGIL_MAP{$sigil});
+        }
+        else {
+            return ("${sigil}${variable}", '', $SIGIL_MAP{''});
+        }
     }
 }
 
@@ -107,6 +110,19 @@ will create C<%Foo::foo>.
 
 =cut
 
+sub _valid_for_type {
+    my $self = shift;
+    my ($value, $type) = @_;
+    if ($type eq 'HASH' || $type eq 'ARRAY'
+     || $type eq 'IO'   || $type eq 'CODE') {
+        return reftype($value) eq $type;
+    }
+    else {
+        my $ref = reftype($value);
+        return !defined($ref) || $ref eq 'SCALAR' || $ref eq 'REF' || $ref eq 'LVALUE';
+    }
+}
+
 sub add_package_symbol {
     my ($self, $variable, $initial_value) = @_;
 
@@ -114,6 +130,11 @@ sub add_package_symbol {
         ? @{$variable}{qw[name sigil type]}
         : $self->_deconstruct_variable_name($variable);
 
+    if (@_ > 2) {
+        $self->_valid_for_type($initial_value, $type)
+            || confess "$initial_value is not of type $type";
+    }
+
     my $pkg = $self->name;
 
     no strict 'refs';