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 int $!rw;
has str $!name; has str $!name;
has $!default; has $!default;
has int $!dynamic;


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


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


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


# "of" traits # "of" traits
Expand Down

0 comments on commit 99993ee

Please sign in to comment.