Last active
January 8, 2016 13:43
-
-
Save niner/88a97e8a1becbacab1d5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
method merge_globals($target, $source) { | |
# Start off merging top-level symbols. Easy when there's no | |
# overlap. Otherwise, we need to recurse. | |
my %known_symbols; | |
for stash_hash($target) { | |
nqp::sayfh(nqp::getstderr(), "Known symbol " ~ $_.key); | |
%known_symbols{$_.key} := 1; | |
} | |
for stash_hash($source) { | |
my $sym := $_.key; | |
nqp::sayfh( | |
nqp::getstderr(), | |
"Checking symbol " ~ $sym | |
~ " value " ~ $_.value.HOW.name($_.value) | |
~ " objid " ~ nqp::objectid($_.value) | |
~ " where " ~ nqp::where($_.value) | |
~ " existing " ~ ($target){$sym}.HOW.name(($target){$sym}) | |
~ " objid " ~ nqp::objectid(($target){$sym}) | |
~ " where " ~ nqp::where(($target){$sym}) | |
~ " eqaddr " ~ nqp::eqaddr(($target){$sym}, $_.value) | |
); | |
if !%known_symbols{$sym} { | |
nqp::sayfh(nqp::getstderr(), "unknown!"); | |
($target){$sym} := $_.value; | |
} | |
elsif ($target){$sym} =:= $_.value { | |
nqp::sayfh(nqp::getstderr(), "symbol already there!"); | |
# No problemo; a symbol can't conflict with itself. | |
} | |
else { | |
nqp::sayfh(nqp::getstderr(), "conflict!"); | |
my $source_mo := $_.value.HOW; | |
my $source_is_stub := $source_mo.HOW.name($source_mo) eq $stub_how | |
|| $source_mo.HOW.name($source_mo) eq $nqp_stub_how; | |
nqp::sayfh(nqp::getstderr(), "source_is_stub: " ~ $source_is_stub ~ " " ~ $source_mo.HOW.name($source_mo)); | |
my $target_mo := ($target){$sym}.HOW; | |
my $target_is_stub := $target_mo.HOW.name($target_mo) eq $stub_how | |
|| $target_mo.HOW.name($target_mo) eq $nqp_stub_how; | |
nqp::sayfh(nqp::getstderr(), "target_is_stub: " ~ $target_is_stub ~ " " ~ $target_mo.HOW.name($target_mo)); | |
if $source_is_stub && $target_is_stub { | |
# Both stubs. We can safely merge the symbols from | |
# the source into the target that's importing them. | |
self.merge_globals(($target){$sym}.WHO, $_.value.WHO); | |
} | |
elsif $source_is_stub { | |
# The target has a real package, but the source is a | |
# stub. Also fine to merge source symbols into target. | |
self.merge_globals(($target){$sym}.WHO, $_.value.WHO); | |
} | |
elsif $target_is_stub { | |
# The tricky case: here the interesting package is the | |
# one in the module. So we merge the other way around | |
# and install that as the result. | |
nqp::sayfh(nqp::getstderr(), "merging symbol $sym"); | |
self.merge_globals($_.value.WHO, ($target){$sym}.WHO); | |
($target){$sym} := $_.value; | |
} | |
elsif nqp::eqat($_.key, '&', 0) { | |
nqp::sayfh(nqp::getstderr(), "function!"); | |
# "Latest wins" semantics for functions | |
($target){$sym} := $_.value; | |
} | |
else { | |
nqp::die("P6M Merging GLOBAL symbols failed: duplicate definition of symbol $sym"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment