Skip to content

Commit

Permalink
Apply a slightly refactored and tweaked patch from sorear++ to add a …
Browse files Browse the repository at this point in the history
…first cut of loading and importing from foreign libraries. Works with Blizkost (tested here on Win32). Not complete/final, but should let people start playing with a few aspects of Perl 5 interop.
  • Loading branch information
jnthn committed Apr 26, 2010
1 parent 6c52872 commit 3a89591
Showing 1 changed file with 63 additions and 4 deletions.
67 changes: 63 additions & 4 deletions src/Perl6/Module/Loader.pm
Expand Up @@ -5,7 +5,12 @@ class Perl6::Module::Loader;
our %LOADED;

method need($name, %name_adverbs?) {
# Use locator to find the module.
# From another HLL?
if %name_adverbs<from> {
return self.need_foreign($name, %name_adverbs);
}

# Otherwise, use the Perl 6 module locator.
my @inc := pir::get_hll_global__PS('@INC');
my $pm_file := %name_adverbs<ver> || %name_adverbs<auth> ??
Perl6::Module::Locator.find_module($name, @inc, %name_adverbs<ver>, %name_adverbs<auth>) !!
Expand Down Expand Up @@ -48,10 +53,63 @@ method need($name, %name_adverbs?) {
1;
}

method need_foreign($name, %name_adverbs) {
# If it's a foreign module, we delegate most of the work to the
# other language. However, we still need to install a namespace
# alias in order for import and qualified references to work.

my $lang := %name_adverbs<from>;
my $orig_name := $name; # TODO: Implement :from<lang not.coloned.Name>

pir::load_language__vs($lang);

my $lsm := pir::compreg__ps($lang);
my $mod := $lsm.load_module($orig_name);
my $ns := $lsm.get_namespace($mod);

# Perl6's two phase import mechanism complicates things slightly
# We need to remember the $lsm to we can get at the exports *later*
my $exports_closure := sub() {
# TODO: Import flags
my %raw_exports := $lsm.get_exports($mod);
my %exports;

my %subs := %raw_exports<sub> // pir::root_new__PP(<parrot Hash>);
for %subs {
%exports{'&' ~ $_.key} := %subs{$_.key};
}
# TODO: Non-sub exports

%exports;
};
pir::setprop($ns, '!rakudo-export-closure', $exports_closure);

# XXX This alias wants to be lexical, but for now we put it into the
# namespace.
my @nsparts := pir::split__PSS('::', $name);
my $lastpart := @nsparts.pop;
pir::set_hll_global__vPSP(@nsparts, '&' ~ $lastpart, sub() { $mod });
pir::set_hll_global__vPSP(@nsparts, $lastpart, $ns);

return 1;
}

method get_imports($name) {
# Look up default export namespace.
# XXX Here is where we need to support custom tags.
my @nsparts := pir::split__PSS('::', $name);

# If it's an alias to a foreign namespace, we attached an export closure
# to it at need time.
my $ns := pir::get_hll_namespace__PP(@nsparts);
unless pir::isnull($ns) {
my $closure := pir::getprop('!rakudo-export-closure', $ns);
unless pir::isnull($closure) {
return $closure();
}
}

# Otherwise, just go looking in EXPORT::DEFAULT namespace.
# XXX Here is where we need to support custom tags.
@nsparts.push('EXPORT');
@nsparts.push('DEFAULT');
return pir::get_hll_namespace__PP(@nsparts);
Expand All @@ -62,10 +120,10 @@ method stub_lexical_imports($name, $block_ast) {
unless pir::isnull__IP(%imports) {
for %imports {
$block_ast[0].push(PAST::Var.new(
:name(~$_), :scope('lexical'), :isdecl(1),
:name($_.key), :scope('lexical'), :isdecl(1),
:viviself(PAST::Op.new( :pirop('null P')) )
));
$block_ast.symbol(~$_, :scope('lexical'));
$block_ast.symbol($_.key, :scope('lexical'));
}
}
}
Expand All @@ -85,5 +143,6 @@ method import($name) {
$targetns{$_.key} := $_.value;
}
}

1;
}

0 comments on commit 3a89591

Please sign in to comment.