Commits

Toby Inkster committed c63ef75

Load-on-demand

Comments (0)

Files changed (3)

lib/RDF/Shortcuts.pm

 }
 
 use parent qw[Exporter];
+use Carp qw[];
 use RDF::Trine;
 use Scalar::Util qw[blessed refaddr];
 
 		};
 }
 
-our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS, %GOT);
+our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS, %GOT_MODULE, %GOT_SYMBOL, %INDEX);
 
-BEGIN
+use RDF::Shortcuts::Index;
+BEGIN {
+	@EXPORT_OK = keys %INDEX;
+	while (my ($s, $m) = each %INDEX)
+	{
+		$m =~ s/^RDF::Shortcuts:://;
+		push @{ $EXPORT_TAGS{$m} }, $s;
+		push @{ $EXPORT_TAGS{lc $m} }, $s unless $s =~ /^rdf_/;
+	}
+	
+	$EXPORT_TAGS{'ALL'}      = @EXPORT_OK;
+	$EXPORT_TAGS{'USEFUL'}   = qw/parse serialize sparql/;
+	$EXPORT_TAGS{'PREFIXED'} = grep { /^rdf_/ } @EXPORT_OK;
+	$EXPORT_TAGS{'BARE'}     = grep {!/^rdf_/ } @EXPORT_OK;
+}
+
+sub import
 {
-	my @modules = qw(Parse Serialise Query Node Statement Pattern);
+	my (@symbols) = @_;
+	shift @symbols if $symbols[0] eq __PACKAGE__;
+	return unless @symbols;
 
-	foreach my $module (@modules)
+	my $no_export;
+	if ($symbols[0] eq ':prepare')
 	{
-		my $class = join '::', __PACKAGE__, $module;
-		unless (eval "use RDF::Shortcuts::$module; 1;")
+		$symbols[0] = ':ALL';
+		$no_export = 1;
+	}
+
+	my @expanded = map { /^:(.+)$/ ? @{ $EXPORT_TAGS{$1} || [Carp::croak "Undefined tag '$_'"] } : ($_) } @symbols;
+	
+	__PACKAGE__->_load_symbols(@expanded);
+	__PACKAGE__->export_to_level(1, __PACKAGE__, @expanded)
+		unless $no_export;
+}
+
+our $AUTOLOAD;
+sub AUTOLOAD
+{
+	my ($function) = ($AUTOLOAD =~ /::([^:]+)$/);
+	my ($coderef)  = __PACKAGE__->_load_symbols($function);
+	return $coderef->(@_);
+}
+
+sub _load_symbols
+{
+	shift;
+	my @rv;
+	
+	foreach my $symbol (@_)
+	{
+		my $module = $INDEX{$symbol};
+		
+		if ($GOT_SYMBOL{$symbol})
 		{
-			warn $@;
-			next;
+			# no-op
+		}
+		elsif (!$module)
+		{
+			Carp::croak "Unknown symbol $symbol";
+		}
+		elsif ($GOT_MODULE{$module})
+		{
+			$GOT_SYMBOL{$symbol} = 1;
+			
+			$module->import($symbol);
+		}
+		elsif (eval "require $module; 1")
+		{
+			$GOT_MODULE{$module} = 1;
+			$GOT_SYMBOL{$symbol} = 1;
+			
+			$module->import($symbol);
+		}
+		else
+		{
+			Carp::croak "Error loading module $module: $@";
 		}
 		
-		$GOT{$module} = TRUE;
-		push @EXPORT, eval "\@${class}::EXPORT";
-		push @EXPORT_OK, eval "\@${class}::EXPORT_OK";
-		my %tags = eval "\%${class}::EXPORT_TAGS";
-		while (my ($tag, $names) = each %tags)
-		{
-			push @{ $EXPORT_TAGS{$tag} }, @$names
-				if ref $names eq 'ARRAY';
-		}
-		$EXPORT_TAGS{lc "$module\_all"} = [ eval "\@${class}::EXPORT_OK" ];
-		$EXPORT_TAGS{lc "$module"} = [ eval "\@${class}::EXPORT" ];
-		
-		$class->import( eval "\@${class}::EXPORT_OK" );
+		push @rv, \&{"$module\::$symbol"};
 	}
-	$EXPORT_TAGS{'all'}      = \@EXPORT_OK;
-	$EXPORT_TAGS{'standard'} = \@EXPORT;
-	$EXPORT_TAGS{'default'}  = \@EXPORT;
+	
+	return @rv;
 }
 
 TRUE;

lib/RDF/Shortcuts/Index.pm

+BEGIN {
+	%RDF::Shortcuts::INDEX = (
+		rdf_node => 'RDF::Shortcuts::Node',
+		node => 'RDF::Shortcuts::Node',
+		rdf_resource => 'RDF::Shortcuts::Node',
+		iri => 'RDF::Shortcuts::Node',
+		resource => 'RDF::Shortcuts::Node',
+		rdf_blank => 'RDF::Shortcuts::Node',
+		blank => 'RDF::Shortcuts::Node',
+		rdf_literal => 'RDF::Shortcuts::Node',
+		literal => 'RDF::Shortcuts::Node',
+		rdf_variable => 'RDF::Shortcuts::Node',
+		variable => 'RDF::Shortcuts::Node',
+		parse => 'RDF::Shortcuts::Parse',
+		rdf_parse => 'RDF::Shortcuts::Parse',
+		pattern => 'RDF::Shortcuts::Pattern',
+		rdf_pattern => 'RDF::Shortcuts::Pattern',
+		serialise => 'RDF::Shortcuts::Serialise',
+		serialize => 'RDF::Shortcuts::Serialise',
+		rdf_serialise => 'RDF::Shortcuts::Serialise',
+		rdf_serialize => 'RDF::Shortcuts::Serialise',
+		rdf_string => 'RDF::Shortcuts::Serialise',
+		statement => 'RDF::Shortcuts::Statement',
+		quad => 'RDF::Shortcuts::Statement',
+		triple => 'RDF::Shortcuts::Statement',
+		rdf_statement => 'RDF::Shortcuts::Statement',
+		rdf_quad => 'RDF::Shortcuts::Statement',
+		rdf_triple => 'RDF::Shortcuts::Statement',
+		);
+}
+
+1;
+
+#!/usr/bin/perl
+
+use lib "lib";
+
+print <<'MODULE';
+BEGIN {
+	%RDF::Shortcuts::INDEX = (
+MODULE
+
+while (my $mod = <lib/RDF/Shortcuts/*.pm>)
+{
+	my $class = $mod;
+	$class =~ s{^lib/}{};
+	$class =~ s{\.pm$}{};
+	$class =~ s{/}{::}g;
+	
+	next if $class eq 'RDF::Shortcuts::Index';
+	
+	require $mod;
+	my @exports = eval "\@${class}::EXPORT_OK";
+	foreach my $e (@exports)
+	{
+		print "\t\t${e} => '${class}',\n";
+	}
+}
+
+print <<'MODULE';
+		);
+}
+
+1;
+
+MODULE