Skip to content

Commit

Permalink
support for "is dynamic" and CALLER:: whining.
Browse files Browse the repository at this point in the history
  • Loading branch information
timo committed Aug 11, 2013
1 parent 8c1cc2b commit 99993ee
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 14 deletions.
3 changes: 3 additions & 0 deletions src/Perl6/Metamodel/ContainerDescriptor.nqp
Expand Up @@ -3,6 +3,7 @@ class Perl6::Metamodel::ContainerDescriptor {
has int $!rw;
has str $!name;
has $!default;
has int $!dynamic;

method BUILD(:$of, :$rw, :$name, :$default) {
$!of := $of;
Expand All @@ -15,10 +16,12 @@ class Perl6::Metamodel::ContainerDescriptor {
method rw() { $!rw }
method name() { $!name }
method default() { $!default }
method dynamic() { $!dynamic }

method set_of($of) { $!of := $of }
method set_rw($rw) { $!rw := $rw }
method set_default($default) { $!default := $default }
method set_dynamic($dynamic) { $!dynamic := $dynamic }

method is_generic() {
$!of.HOW.archetypes.generic
Expand Down
29 changes: 18 additions & 11 deletions src/core/PseudoStash.pm
Expand Up @@ -8,7 +8,8 @@ my class PseudoStash is EnumMap {
my int constant PICK_CHAIN_BY_NAME = 0;
my int constant STATIC_CHAIN = 1;
my int constant DYNAMIC_CHAIN = 2;
my int constant PRECISE_SCOPE = 3;
my int constant PRECISE_SCOPE = 4;
my int constant REQUIRE_DYNAMIC = 8;

method new() {
my $obj := nqp::create(self);
Expand Down Expand Up @@ -45,7 +46,7 @@ my class PseudoStash is EnumMap {
my $stash := nqp::create(PseudoStash);
nqp::bindattr($stash, EnumMap, '$!storage', nqp::ctxlexpad($ctx));
nqp::bindattr($stash, PseudoStash, '$!ctx', $ctx);
nqp::bindattr_i($stash, PseudoStash, '$!mode', PRECISE_SCOPE);
nqp::bindattr_i($stash, PseudoStash, '$!mode', PRECISE_SCOPE +| REQUIRE_DYNAMIC);
nqp::setwho(
Metamodel::ModuleHOW.new_type(:name('CALLER')),
$stash);
Expand Down Expand Up @@ -108,13 +109,19 @@ my class PseudoStash is EnumMap {
if %pseudoers.exists($key) {
%pseudoers{$key}(self)
}
elsif $!mode == PRECISE_SCOPE {
elsif nqp::bitand_i($!mode, PRECISE_SCOPE) {
my Mu $store := nqp::getattr(self, EnumMap, '$!storage');
nqp::existskey($store, nqp::unbox_s($key)) ??
nqp::atkey($store, nqp::unbox_s($key)) !!
Any
my Mu $res := nqp::existskey($store, nqp::unbox_s($key)) ??
nqp::atkey($store, nqp::unbox_s($key)) !!
Any;
if !($res =:= Any) && nqp::bitand_i($!mode, REQUIRE_DYNAMIC) {
if !$res.VAR.dynamic {
die "You're trying to access a non-dynamic variable through CALLER.";
}
}
$res;
}
elsif $!mode == DYNAMIC_CHAIN || $!mode == PICK_CHAIN_BY_NAME && substr($key, 1, 1) eq '*' {
elsif nqp::bitand_i($!mode, nqp::bitor_i(DYNAMIC_CHAIN, PICK_CHAIN_BY_NAME)) && substr($key, 1, 1) eq '*' {
my $found := nqp::getlexreldyn(
nqp::getattr(self, PseudoStash, '$!ctx'),
nqp::unbox_s($key));
Expand All @@ -133,11 +140,11 @@ my class PseudoStash is EnumMap {
if %pseudoers.exists($key) {
X::Bind.new(target => "pseudo-package $key").throw;
}
elsif $!mode == PRECISE_SCOPE {
elsif nqp::bitand_i($!mode, PRECISE_SCOPE) {
my Mu $store := nqp::getattr(self, EnumMap, '$!storage');
nqp::bindkey($store, nqp::unbox_s($key), value)
}
elsif $!mode == DYNAMIC_CHAIN || $!mode == PICK_CHAIN_BY_NAME && substr($key, 1, 1) eq '*' {
elsif nqp::bitand_i($!mode, nqp::bitor_i(DYNAMIC_CHAIN, PICK_CHAIN_BY_NAME)) && substr($key, 1, 1) eq '*' {
die "Binding to dynamic variables not yet implemented";
}
else {
Expand All @@ -150,12 +157,12 @@ my class PseudoStash is EnumMap {
if %pseudoers.exists($key) {
True
}
elsif $!mode == PRECISE_SCOPE {
elsif nqp::bitand_i($!mode, PRECISE_SCOPE) {
nqp::p6bool(nqp::existskey(
nqp::getattr(self, EnumMap, '$!storage'),
nqp::unbox_s($key)))
}
elsif $!mode == DYNAMIC_CHAIN || $!mode == PICK_CHAIN_BY_NAME && substr($key, 1, 1) eq '*' {
elsif nqp::bitand_i($!mode, nqp::bitor_i(DYNAMIC_CHAIN, PICK_CHAIN_BY_NAME)) && substr($key, 1, 1) eq '*' {
nqp::isnull(
nqp::getlexreldyn(
nqp::getattr(self, PseudoStash, '$!ctx'),
Expand Down
4 changes: 4 additions & 0 deletions src/core/Scalar.pm
Expand Up @@ -12,4 +12,8 @@ my class Scalar {
my $d := $!descriptor;
nqp::isnull($d) ?? Mu !! $d.default;
}
method dynamic() {
my $d := $!descriptor;
nqp::isnull($d) ?? Mu !! $d.dynamic;
}
}
12 changes: 9 additions & 3 deletions src/core/Variable.pm
Expand Up @@ -46,9 +46,15 @@ multi trait_mod:<is>(Variable:D $v, :$default!) {
).set_default($default);
}
multi trait_mod:<is>(Variable:D $v, :$dynamic!) {
# must be a noop for now, as apparently outer scope lexicals are *always*
# visible with the CALLER:: interface, even if they're *not* marked as
# "is dynamic"
my $var := $v.var;
my $what := $var.VAR.WHAT;
nqp::getattr(
$var,
$what.perl ~~ m/\+/ # we have types mixed in
?? $what.^mro[1] # (Hash+{TypedHash}) -> (Hash)
!! $what,
'$!descriptor',
).set_dynamic($dynamic);
}

# "of" traits
Expand Down

0 comments on commit 99993ee

Please sign in to comment.