File Coverage

blib/lib/Inline/Wrapper.pm
Criterion Covered Total %
statement 90 104 86.5
branch 15 36 41.6
condition 3 25 12.0
subroutine 26 28 92.8
pod 14 14 100.0
total 148 207 71.5


line stmt bran cond sub pod time code
1             package Inline::Wrapper;
2             #
3             # Inline::* module dynamic loader and useful wrapper routines
4             #
5             # $Id: Wrapper.pm 14 2010-03-10 09:08:18Z infidel $
6             #
7             # POD documentation after __END__
8             #
9              
10 6     6   340804 use strict;
  6         18  
  6         210  
11 6     6   33 use warnings;
  6         13  
  6         201  
12 6     6   31 use Carp qw( carp croak );
  6         17  
  6         917  
13 6     6   6792 use Data::Dumper;
  6         75885  
  6         518  
14 6     6   56 use vars qw( $TRUE $FALSE $VERSION );
  6         11  
  6         421  
15 6   50 6   149 BEGIN { $INC{'Inline::Wrapper.pm'} ||= __FILE__ }; # recursive use check
16 6     6   3973 use Inline::Wrapper::Module; # individual code modules
  6         19  
  6         9594  
17              
18             ###
19             ### VARS
20             ###
21              
22             $VERSION = '0.05';
23             *TRUE = \1;
24             *FALSE = \0;
25              
26             my $DEFAULTS = {
27             base_dir => '.', # default search directory
28             auto_reload => $FALSE, # automatically reload module?
29             language => 'Lua', # default language
30             };
31              
32             my $LANGS = {
33             Foo => '.foo', # built in to Inline's distro
34             C => '.c',
35             Lua => '.lua',
36             # 'C++' => '.cpp',
37             # Java => '.java',
38             # Python => '.py',
39             # Tcl => '.tcl',
40             # Ruby => '.rb',
41             };
42              
43             my $PARAMS = {
44             base_dir => sub { $_[0] },
45             auto_reload => sub { $_[0] ? $TRUE : $FALSE },
46             language => sub {
47             defined( $_[0] ) and exists( $LANGS->{$_[0]} )
48             ? $_[0]
49             : ( carp sprintf( "Invalid language: %s; using %s",
50             $_[0], $DEFAULTS->{language} )
51             and $DEFAULTS->{language} )
52             },
53             };
54              
55             ###
56             ### CONSTRUCTOR
57             ###
58              
59             sub new
60             {
61 7     7 1 3262 my( $class, @args ) = @_;
62              
63             # Check parameters
64 7 50       35 @args = %{ $args[0] } if( ref( $args[0] ) eq 'HASH' );
  0         0  
65 7 50       40 croak "$class: \%args must be a hash; read the docs" if( @args & 1 );
66              
67             # Set up object
68 7         165 my $self = {
69             %$DEFAULTS,
70             # modules => {},
71             };
72 7         26 bless( $self, $class );
73              
74             # Initialize object instance
75 7         43 @args = $self->_process_args( @args );
76 7         32 $self->initialize( @args );
77              
78 7         48 return( $self );
79             }
80              
81             sub initialize
82             {
83 6     6 1 13 my( $self ) = @_;
84              
85 6         20 $self->{modules} = {};
86              
87 6         14 return;
88             }
89              
90             ###
91             ### PUBLIC METHODS
92             ###
93              
94             # Load a code module named $modname from $base_dir with $lang_extension
95             sub load
96             {
97 1     1 1 3 my( $self, $modname, @args ) = @_;
98              
99             # Check arguments
100 1 50       5 croak "load() \$modname is a required param; read the docs"
101             unless( $modname );
102 1 50       5 @args = %{ $args[0] } if( ref( $args[0] ) eq 'HASH' );
  0         0  
103 1 50       4 croak "load(): \%args must be a hash; read the docs"
104             if( @args & 1 );
105 1         3 my %args = @args;
106              
107             # Check for duplicate modules, return @function list if found
108             # XXX: Possible bug; should probably issue reload if auto_reload
109             # ends up being set to true.
110 1 50       4 if( my $temp_module = $self->_module( $modname ) )
111             {
112 0   0     0 my $temp_lang = $args{language} || $self->language();
113 0   0     0 my $temp_base_dir = $args{base_dir} || $self->base_dir();
114 0 0 0     0 if( $temp_lang eq $temp_module->language() &&
115             $temp_base_dir eq $temp_module->base_dir() )
116             {
117 0 0       0 $temp_module->set_auto_reload( $args{auto_reload} )
118             if( $args{auto_reload} );
119 0         0 print "HONK!\n";
120 0         0 return( $temp_module->_function_list() ); # RETURN
121             }
122             }
123              
124             # Create a new module object
125 1         5 my $module = Inline::Wrapper::Module->new(
126             module_name => $modname,
127             lang_ext => $self->_lang_ext(),
128             $self->_settings(),
129             %args,
130             );
131 1         5 $self->_add_module( $modname, $module );
132              
133             # Actually attempt to load the inline module
134 1         5 my @functions = $module->_load();
135              
136 1         18 return( @functions );
137             }
138              
139             # Completely unload a loaded $modname, rendering its functions uncallable
140             sub unload
141             {
142 1     1 1 3 my( $self, $modname ) = @_;
143              
144 1 50 0     5 carp "$modname not loaded" and return
145             unless( ref( $self->_module( $modname ) ) );
146              
147 1   33     6 return( $self->_del_module( $modname ) && $modname );
148             }
149              
150             # Run a $modname::$funcname function, passing it @args
151             sub run
152             {
153 1     1 1 5 my( $self, $modname, $funcname, @args ) = @_;
154              
155 1         6 my $module = $self->_module( $modname );
156 1         8 my @retvals = $module->_run( $funcname, @args );
157              
158 1         7 return( @retvals );
159             }
160              
161             # Return the list of already-loaded modules
162             sub modules
163             {
164 4     4 1 10 my( $self ) = @_;
165              
166 4         17 return( $self->_module_names() );
167             }
168              
169             # Return the list of functions loaded from $modname
170             sub functions
171             {
172 1     1 1 5 my( $self, $modname ) = @_;
173              
174 1         4 my $module = $self->_module( $modname );
175 1 50 0     6 carp "Module '$modname' not loaded"
176             and return()
177             unless( ref( $module ) );
178              
179 1         8 return( $module->_function_list() );
180             }
181              
182             ###
183             ### PRIVATE METHODS
184             ###
185              
186             sub _process_args
187             {
188 7     7   51 my( $self, @args ) = @_;
189 7 50       28 croak "_process_args() requires an even number of params" if( @args & 1 );
190 7         27 my %args = @args;
191              
192 7         25 for( keys %args )
193             {
194 15 100       54 next unless( exists( $PARAMS->{lc $_} ) ); # not for us, pass on
195 13         55 $self->{lc $_} = $PARAMS->{lc $_}->( $args{$_} );
196 13         35 delete( $args{$_} );
197             }
198              
199 7         35 return( %args );
200             }
201              
202             sub _module_names
203             {
204 4     4   8 my( $self ) = @_;
205              
206 4         7 return( keys( %{ $self->{modules} } ) );
  4         31  
207             }
208              
209             sub _settings
210             {
211 1     1   3 my( $self ) = @_;
212              
213 1         4 my %defaults = map { $_ => $self->{$_} } keys( %$DEFAULTS );
  3         12  
214              
215 1         15 return( %defaults );
216             }
217              
218             ###
219             ### ACCESSORS
220             ###
221              
222             sub base_dir
223             {
224 7     7 1 22 my( $self ) = @_;
225              
226 7         54 return( $self->{base_dir} );
227             }
228              
229             sub set_base_dir
230             {
231 0     0 1 0 my( $self, $base_dir ) = @_;
232              
233             # Validate
234 0         0 $base_dir = $PARAMS->{base_dir}->( $base_dir );
235              
236 0 0       0 return( defined( $base_dir )
237             ? $self->{base_dir} = $base_dir
238             : $self->{base_dir} );
239             }
240              
241             sub language
242             {
243 6     6 1 16 my( $self ) = @_;
244              
245 6         97 return( $self->{language} );
246             }
247              
248             sub set_language
249             {
250 2     2 1 8 my( $self, $language ) = @_;
251              
252             # Validate
253 2         6 $language = $PARAMS->{language}->( $language );
254              
255 2 50       15 return( defined( $language )
256             ? $self->{language} = $language
257             : $self->{language} );
258             }
259              
260             sub add_language
261             {
262 2     2 1 5 my( $self, $language, $lang_ext ) = @_;
263              
264 2 50 0     9 carp "add_language(): Language not set; read the docs"
265             and return
266             unless( $language );
267 2 50 0     8 carp "add_language(): Language extension not set; read the docs"
268             and return
269             unless( $lang_ext );
270              
271 2 50       17 return( ( $LANGS->{$language} = $lang_ext ) ? $language : undef );
272             }
273              
274             sub auto_reload
275             {
276 7     7 1 73 my( $self ) = @_;
277              
278 7         38 return( $self->{auto_reload} );
279             }
280              
281             sub set_auto_reload
282             {
283 0     0 1 0 my( $self, $auto_reload ) = @_;
284              
285             # Validate
286 0         0 $auto_reload = $PARAMS->{auto_reload}->( $auto_reload );
287              
288 0 0       0 return( defined( $auto_reload )
289             ? $self->{auto_reload} = $auto_reload
290             : $self->{auto_reload} );
291             }
292              
293             ### PRIVATE ACCESSORS
294              
295             sub _module
296             {
297 4     4   10 my( $self, $modname ) = @_;
298              
299 4         24 return( $self->{modules}->{$modname} );
300             }
301              
302             sub _add_module
303             {
304 1     1   2 my( $self, $modname, $module ) = @_;
305              
306 1         5 return( $self->{modules}->{$modname} = $module );
307             }
308              
309             sub _del_module
310             {
311 1     1   2 my( $self, $modname ) = @_;
312              
313             # Namespace is deleted by $module->DESTROY()
314 1         14 return( delete( $self->{modules}->{$modname} ) );
315             }
316              
317             ###
318             ### PRIVATE UTILITY ROUTINES
319             ###
320              
321             sub _lang_ext
322             {
323 8     8   21 my( $self, $language ) = @_;
324              
325 8   33     61 $language ||= $self->{language};
326              
327 8         514 return( $LANGS->{$language} );
328             }
329              
330             1;
331              
332             __END__