Skip to content

Commit

Permalink
Merge pull request #4602 from vrurg/rakudo_1433
Browse files Browse the repository at this point in the history
Clarify let and temp operators
  • Loading branch information
vrurg committed Nov 2, 2021
2 parents a8329f6 + 1fec0ef commit 8986875
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 25 deletions.
37 changes: 25 additions & 12 deletions src/Perl6/World.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -2787,8 +2787,7 @@ class Perl6::World is HLL::World {
QAST::Var.new( :name($value_stash), :scope('lexical'), :decl('var') ),
QAST::Op.new(
:op('create'),
QAST::WVal.new( :value(self.find_single_symbol('IterationBuffer', :setting-only))),
)));
QAST::WVal.new( :value(self.find_single_symbol('IterationBuffer', :setting-only))))));
$block.symbol($value_stash, :scope('lexical'));

# Create a phaser block that will do the restoration.
Expand All @@ -2798,18 +2797,32 @@ class Perl6::World is HLL::World {
:op('while'),
QAST::Op.new(
:op('elems'),
QAST::Var.new( :name($value_stash), :scope('lexical') )
),
QAST::Var.new( :name($value_stash), :scope('lexical') )),
QAST::Op.new(
:op('p6store'),
QAST::Op.new(
:op('shift'),
QAST::Var.new( :name($value_stash), :scope('lexical') )
),
:op('if'),
QAST::Op.new(
:op('shift'),
QAST::Var.new( :name($value_stash), :scope('lexical') )
))));
:op('iscont'),
QAST::Op.new(
:op('atpos'),
QAST::Var.new( :name($value_stash), :scope('lexical') ),
QAST::IVal.new( :value(0) ))),
QAST::Op.new( # p6store is for Scalar
:op('p6store'),
QAST::Op.new(
:op('shift'),
QAST::Var.new( :name($value_stash), :scope('lexical') )),
QAST::Op.new(
:op('shift'),
QAST::Var.new( :name($value_stash), :scope('lexical') ))),
QAST::Op.new( # Otherwise we restore by means of the container itself
:op('callmethod'),
:name('TEMP-LET-RESTORE'),
QAST::Op.new(
:op('shift'),
QAST::Var.new( :name($value_stash), :scope('lexical') )),
QAST::Op.new(
:op('shift'),
QAST::Var.new( :name($value_stash), :scope('lexical') ))))));

# Add as phaser.
$block[0].push($phaser_block);
Expand Down
21 changes: 21 additions & 0 deletions src/core.c/Array.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,27 @@ my class Array { # declared in BOOTSTRAP
}
}

my class LTHandle {
has Mu $!reified;
has Mu $!todo;
has Mu $!descriptor;
}

method TEMP-LET-LOCALIZE() is raw is implementation-detail {
my \handle = nqp::create(LTHandle);
nqp::bindattr(handle, LTHandle, '$!reified', nqp::getattr(self, List, '$!reified'));
nqp::bindattr(handle, LTHandle, '$!todo', nqp::getattr(self, List, '$!todo'));
nqp::bindattr(handle, LTHandle, '$!descriptor', nqp::getattr(self, Array, '$!descriptor'));
self.STORE: self.clone;
handle
}

method TEMP-LET-RESTORE(\handle --> Nil) is implementation-detail {
nqp::bindattr(self, List, '$!reified', nqp::getattr(handle, LTHandle, '$!reified'));
nqp::bindattr(self, List, '$!todo', nqp::getattr(handle, LTHandle, '$!todo'));
nqp::bindattr(self, Array, '$!descriptor', nqp::getattr(handle, LTHandle, '$!descriptor'));
}

method ^parameterize(Mu:U \arr, Mu \of) {
if nqp::isconcrete(of) {
die "Can not parameterize {arr.^name} with {of.raku}"
Expand Down
36 changes: 36 additions & 0 deletions src/core.c/Hash.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,42 @@ my class Hash { # declared in BOOTSTRAP
!! (current = self.EXISTS-KEY($key) ?? [|current,|value] !! value)
}

my class LTHandle {
has Mu $!storage;
has Mu $!descriptor;
}

method TEMP-LET-GET-HANDLE() is raw is implementation-detail {
my \handle = nqp::create(LTHandle);
nqp::bindattr(handle, LTHandle, '$!storage', nqp::getattr(self, Map, '$!storage'));
nqp::bindattr(handle, LTHandle, '$!descriptor', nqp::getattr(self, Hash, '$!descriptor'));
handle
}

method TEMP-LET-LOCALIZE() is raw is implementation-detail {
my \handle = self.TEMP-LET-GET-HANDLE;
# Re-initialize self from the original state by taking into account conterization status of keys.
my \iter = nqp::iterator(nqp::getattr(self, Map, '$!storage'));
nqp::bindattr(self, Map, '$!storage', my \new-storage = nqp::hash);
nqp::while(
iter,
nqp::stmts(
nqp::shift(iter),
(my \v = nqp::iterval(iter)),
nqp::bindkey(
new-storage,
nqp::iterkey_s(iter),
nqp::if( nqp::iscont(v),
nqp::p6assign(nqp::p6scalarfromdesc(nqp::getattr(self, Hash, '$!descriptor')), v),
v ))));
handle
}

method TEMP-LET-RESTORE(\handle --> Nil) is implementation-detail {
nqp::bindattr(self, Hash, '$!descriptor', nqp::getattr(handle, LTHandle, '$!descriptor'));
nqp::bindattr(self, Map, '$!storage', nqp::getattr(handle, LTHandle, '$!storage'));
}

method ^parameterize(Mu:U \hash, Mu \of, Mu \keyof = Str(Any)) {

# fast path
Expand Down
21 changes: 21 additions & 0 deletions src/core.c/Hash/Object.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,27 @@ my role Hash::Object[::TValue, ::TKey] does Associative[TValue] {
!! nqp::create(Capture)
}
method Map() { self.pairs.Map }

method TEMP-LET-LOCALIZE() is raw is implementation-detail {
my \handle = self.TEMP-LET-GET-HANDLE;
my \iter = nqp::iterator(nqp::getattr(self, Map, '$!storage'));
nqp::bindattr(self, Map, '$!storage', my \new-storage = nqp::hash);
nqp::while(
iter,
nqp::stmts(
nqp::shift(iter),
# What we do here is very much stripped down versions of ASSIGN-KEY and BIND-KEY.
(my \p = nqp::iterval(iter)),
nqp::bindkey(
new-storage,
nqp::iterkey_s(iter),
Pair.new(
p.key,
nqp::if( nqp::iscont(my \v = p.value),
nqp::p6assign(nqp::p6scalarfromdesc(nqp::getattr(self, Hash, '$!descriptor')), v),
v )))));
handle
}
}

# vim: expandtab shiftwidth=4
18 changes: 5 additions & 13 deletions src/core.c/Rakudo/Internals.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -227,19 +227,11 @@ my class Rakudo::Internals {
nqp::iscont(cont),
nqp::push(restore,nqp::decont(cont)),
nqp::if(
nqp::istype(cont,Array),
nqp::push(restore,cont.clone),
nqp::if(
nqp::istype(cont,Hash),
nqp::push(restore,
nqp::p6bindattrinvres(
Hash.^parameterize(Mu,Mu).new,
Hash, '$!descriptor',
nqp::getattr(cont, Hash, '$!descriptor')).STORE: cont),
nqp::stmts(
nqp::pop(restore), # lose the erroneously pushed value
X::Localizer::NoContainer.new(:$localizer).throw
)
nqp::can(cont,'TEMP-LET-LOCALIZE'),
nqp::push(restore,cont.TEMP-LET-LOCALIZE),
nqp::stmts(
nqp::pop(restore), # lose the erroneously pushed value
X::Localizer::NoContainer.new(:$localizer).throw
)
)
)
Expand Down

0 comments on commit 8986875

Please sign in to comment.