5
method search_path($explicit_path) {
8
# Put any explicitly specified path on the start of the list.
10
if !nqp::isnull($explicit_path) {
11
try { my $hack; $explicit := %*COMPILING<%?OPTIONS>{$explicit_path}; }
13
if !nqp::isnull($explicit) && nqp::defined($explicit) {
14
nqp::push(@search_paths, $explicit);
17
for nqp::jvmclasspaths() {
18
nqp::push(@search_paths, $_)
23
nqp::push(@search_paths, '.');
24
nqp::push(@search_paths, 'blib');
30
$*MAIN_CTX := nqp::ctxcaller(nqp::ctx());
34
method load_module($module_name, *@extras, :$line, :$file) {
35
# If we didn't already do so, load the module and capture
36
# its mainline. Otherwise, we already loaded it so go on
37
# with what we already have.
39
my $path := nqp::join('/', nqp::split('::', $module_name));
40
my @prefixes := self.search_path('module-path');
41
for @prefixes -> $prefix {
42
if nqp::stat("$prefix/$path.jar", 0) {
43
$path := "$prefix/$path.jar";
46
if nqp::stat("$prefix/$path.class", 0) {
47
$path := "$prefix/$path.class";
51
if nqp::existskey(%modules_loaded, $path) {
52
$module_ctx := %modules_loaded{$path};
56
my $*MAIN_CTX := ModuleLoader;
58
try { my $hack; $boot_mode := %*COMPILING<%?OPTIONS><bootstrap>; }
59
$boot_mode := !nqp::isnull($boot_mode) && $boot_mode;
60
my $preserve_global := nqp::getcurhllsym('GLOBAL');
61
nqp::usecompileehllconfig() if $boot_mode;
62
nqp::loadbytecode($path);
63
nqp::usecompilerhllconfig() if $boot_mode;
64
nqp::bindcurhllsym('GLOBAL', $preserve_global);
65
%modules_loaded{$path} := $module_ctx := $*MAIN_CTX;
68
# Provided we have a mainline...
69
if nqp::defined($module_ctx) {
71
my $UNIT := nqp::ctxlexpad($module_ctx);
72
unless nqp::isnull($UNIT<GLOBALish>) {
73
if nqp::elems(@extras) {
74
# There can be a hash at index zero, which contains adverbs
75
# passed to the use-statement.
76
my $index := nqp::ishash(@extras[0]) ?? 1 !! 0;
77
if nqp::elems(@extras) > $index {
78
merge_globals(@extras[$index], $UNIT<GLOBALish>);
87
# XXX This is a really dumb and minimalistic GLOBAL merger.
88
# For a much more complete one, see sorear++'s work in
89
# Niecza. This one will likely evolve towards that, but for
90
# now I just need something that's just good enough for the
91
# immediate needs of NQP bootstrapping.
92
my $stub_how := 'KnowHOW';
93
sub merge_globals($target, $source) {
94
# XXX For now just merge the top level symbols;
95
# if there's a conflict then don't dig any deeper.
96
# Obviously, just a first cut at this. :-)
99
%known_symbols{nqp::iterkey_s($_)} := 1;
102
my $sym := nqp::iterkey_s($_);
103
my $val := nqp::iterval($_);
104
if !nqp::existskey(%known_symbols, $sym) {
105
my $source_is_stub := 0;
106
# XXX TODO: Exceptions.
108
my $source_mo := $val.HOW;
109
$source_is_stub := $source_mo.WHAT.HOW.name($source_mo) eq $stub_how &&
110
!nqp::isnull(nqp::who($val)) && nqp::who($val);
114
my $source_clone := $source.HOW.new_type(:name($source.HOW.name($source)));
115
$source_clone.HOW.compose($source_clone);
117
for nqp::who($source) {
118
%WHO_clone{nqp::iterkey_s($_)} := nqp::iterval($_);
120
nqp::setwho($source_clone, %WHO_clone);
121
($target.WHO){$sym} := $source_clone;
124
($target.WHO){$sym} := $val;
127
elsif ($target.WHO){$sym} =:= $val {
128
# No problemo; a symbol can't conflict with itself.
131
my $source_mo := $val.HOW;
132
my $source_is_stub := $source_mo.WHAT.HOW.name($source_mo) eq $stub_how;
133
my $target_mo := ($target.WHO){$sym}.HOW;
134
my $target_is_stub := $target_mo.WHAT.HOW.name($target_mo) eq $stub_how;
135
if $source_is_stub && $target_is_stub {
136
# Leave target as is, and merge the nested symbols.
137
merge_globals(($target.WHO){$sym}, $val);
140
nqp::die("Merging GLOBAL symbols failed: duplicate definition of symbol $sym");
146
method load_setting($setting_name) {
149
if $setting_name ne 'NULL' {
150
# Add path prefix and .setting suffix.
151
my $path := "$setting_name.setting";
152
my @prefixes := self.search_path('setting-path');
153
for @prefixes -> $prefix {
154
if nqp::stat("$prefix/$path.jar", 0) {
155
$path := "$prefix/$path.jar";
158
if nqp::stat("$prefix/$path.class", 0) {
159
$path := "$prefix/$path.class";
164
# Unless we already did so, load the setting.
165
unless nqp::existskey(%settings_loaded, $path) {
166
my $*CTXSAVE := self;
167
my $*MAIN_CTX := ModuleLoader;
169
try { my $hack; $boot_mode := %*COMPILING<%?OPTIONS><bootstrap>; }
170
$boot_mode := !nqp::isnull($boot_mode) && $boot_mode;
171
my $preserve_global := nqp::getcurhllsym('GLOBAL');
172
nqp::usecompileehllconfig() if $boot_mode;
173
nqp::loadbytecode($path);
174
nqp::usecompilerhllconfig() if $boot_mode;
175
nqp::bindcurhllsym('GLOBAL', $preserve_global);
176
unless nqp::defined($*MAIN_CTX) {
177
nqp::die("Unable to load setting $setting_name; maybe it is missing a YOU_ARE_HERE?");
179
%settings_loaded{$path} := $*MAIN_CTX;
182
$setting := %settings_loaded{$path};
189
# Since this *is* the module loader, we can't locate it the normal way by
190
# GLOBAL merging. So instead we stash it away in the Parrot namespace tree.
191
nqp::bindcurhllsym('ModuleLoader', ModuleLoader);