Skip to content

Commit

Permalink
Make Set/SetHash parameterizable
Browse files Browse the repository at this point in the history
- if class is parameterized, then a custom "keyof" method is mixed in
- and the name is changed
- also fixes .keyof method for default from Any -> Mu
- reverts 0d9e9f3
- fixes RT#133762
  • Loading branch information
lizmat committed Jan 13, 2019
1 parent 081b15e commit 4bb5c33
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/core/Iterable.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ my role Iterable {

sub SETIFY(\iterable, \type) {
nqp::if(
(my $iterator := iterable.flat.iterator).is-lazy,
(my \iterator := iterable.flat.iterator).is-lazy,
Failure.new(X::Cannot::Lazy.new(:action<coerce>,:what(type.^name))),
nqp::if(
nqp::elems(my $elems := Rakudo::QuantHash.ADD-PAIRS-TO-SET(
nqp::create(Rakudo::Internals::IterationSet),$iterator
nqp::create(Rakudo::Internals::IterationSet),iterator,Mu
)),
nqp::create(type).SET-SELF($elems),
nqp::if(
Expand Down
18 changes: 9 additions & 9 deletions src/core/QuantHash.pm6
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
my role QuantHash[::CONSTRAINT = Mu] does Associative {
my role QuantHash does Associative {

method keyof(::?CLASS:D:) { CONSTRAINT }
method keyof() { Mu }

method SET-SELF(::?CLASS:D: \elems) { # cannot be a private method
method SET-SELF(QuantHash:D: \elems) { # cannot be a private method
nqp::stmts(
nqp::if(
nqp::elems(elems),
Expand All @@ -18,17 +18,17 @@ my role QuantHash[::CONSTRAINT = Mu] does Associative {
X::Assignment::RO.new(value => self).throw
}

method Int (::?CLASS:D: --> Int:D) { self.total.Int }
method Num (::?CLASS:D: --> Num:D) { self.total.Num }
method Numeric (::?CLASS:D: --> Numeric:D) { self.total.Numeric }
method Real (::?CLASS:D: --> Real:D) { self.total.Real }
method Int ( --> Int:D) { self.total.Int }
method Num ( --> Num:D) { self.total.Num }
method Numeric ( --> Numeric:D) { self.total.Numeric }
method Real ( --> Real:D) { self.total.Real }

method Capture(::?CLASS:D:) { self.Hash.Capture }
method Capture() { self.Hash.Capture }

multi method list(QuantHash:U:) { self.Any::list }
multi method list(QuantHash:D:) { self.pairs.cache }

method fmt(::?CLASS: Cool $format = "%s\t\%s", $sep = "\n") {
method fmt(QuantHash: Cool $format = "%s\t\%s", $sep = "\n") {
nqp::iseq_i(nqp::sprintfdirectives( nqp::unbox_s($format.Stringy)),1)
?? self.keys.fmt($format, $sep)
!! self.pairs.fmt($format, $sep)
Expand Down
4 changes: 4 additions & 0 deletions src/core/Rakudo/Internals.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ my class Rakudo::Internals {
)
}

our role Constraint[::CONSTRAINT] {
method keyof() { CONSTRAINT }
}

our role ImplementationDetail {
method new(|) { die self.gist }
method gist(--> Str:D) {
Expand Down
35 changes: 23 additions & 12 deletions src/core/Rakudo/QuantHash.pm6
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
my role Real { ... }
my class X::TypeCheck::Binding { ... }

my class Rakudo::QuantHash {

Expand Down Expand Up @@ -294,40 +295,50 @@ my class Rakudo::QuantHash {
)
}

# bind the given value to the given IterationSet, check for given type
method BIND-TO-TYPED-SET(\elems, Mu \value, Mu \type --> Nil) {
nqp::if(
nqp::istype(value,type),
nqp::bindkey(elems,value.WHICH,value),
X::TypeCheck::Binding.new(
got => value.WHAT,
expected => type
).throw
)
}

# add to given IterationSet with setty semantics the values of iterator
method ADD-ITERATOR-TO-SET(\elems,Mu \iterator) {
method ADD-ITERATOR-TO-SET(\elems,Mu \iterator, Mu \type) {
nqp::stmts(
nqp::until(
nqp::eqaddr(
(my $pulled := nqp::decont(iterator.pull-one)),
(my \pulled := nqp::decont(iterator.pull-one)),
IterationEnd
),
nqp::bindkey(elems,$pulled.WHICH,$pulled)
self.BIND-TO-TYPED-SET(elems, pulled, type)
),
elems
)
}

# Add to IterationSet with setty semantics the values of the given
# iterator while checking for Pairs (only include if value is trueish)
method ADD-PAIRS-TO-SET(\elems,Mu \iterator) {
method ADD-PAIRS-TO-SET(\elems,Mu \iterator, Mu \type) {
nqp::stmts(
nqp::until(
nqp::eqaddr(
(my $pulled := nqp::decont(iterator.pull-one)),
(my \pulled := nqp::decont(iterator.pull-one)),
IterationEnd
),
nqp::if(
nqp::istype($pulled,Pair),
nqp::istype(pulled,Pair),
nqp::if(
nqp::getattr($pulled,Pair,'$!value'),
nqp::bindkey(
elems,
nqp::getattr($pulled,Pair,'$!key').WHICH,
nqp::getattr($pulled,Pair,'$!key')
nqp::getattr(pulled,Pair,'$!value'),
self.BIND-TO-TYPED-SET(
elems, nqp::getattr(pulled,Pair,'$!key'), type
)
),
nqp::bindkey(elems,$pulled.WHICH,$pulled)
self.BIND-TO-TYPED-SET(elems, pulled, type)
)
),
elems
Expand Down
13 changes: 11 additions & 2 deletions src/core/Set.pm6
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
my class Set does Setty {
has ValueObjAt $!WHICH;

method ^parameterize(Mu \base, Mu \type) {
my \what := base.^mixin(Rakudo::Internals::Constraint[type]);
what.^set_name(base.^name ~ '[' ~ type.^name ~ ']');
what
}

multi method WHICH (Set:D: --> ValueObjAt:D) {
nqp::if(
nqp::attrinited(self,Set,'$!WHICH'),
Expand Down Expand Up @@ -93,11 +99,14 @@ my class Set does Setty {

#--- interface methods
multi method STORE(Set:D: *@pairs, :$INITIALIZE! --> Set:D) {
(my $iterator := @pairs.iterator).is-lazy
(my \iterator := @pairs.iterator).is-lazy
?? Failure.new(
X::Cannot::Lazy.new(:action<initialize>,:what(self.^name)))
!! self.SET-SELF(Rakudo::QuantHash.ADD-PAIRS-TO-SET(
nqp::create(Rakudo::Internals::IterationSet), $iterator))
nqp::create(Rakudo::Internals::IterationSet),
iterator,
self.keyof
))
}
multi method STORE(Set:D: \objects, \bools, :$INITIALIZE! --> Set:D) {
self.SET-SELF(
Expand Down
14 changes: 10 additions & 4 deletions src/core/SetHash.pm6
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
my class SetHash does Setty {

method ^parameterize(Mu \base, Mu \type) {
my \what := base.^mixin(Rakudo::Internals::Constraint[type]);
what.^set_name(base.^name ~ '[' ~ type.^name ~ ']');
what
}

#--- selector methods

multi method grab(SetHash:D:) {
Expand Down Expand Up @@ -189,7 +195,7 @@ my class SetHash does Setty {
Failure.new(X::Cannot::Lazy.new(:action<initialize>,:what(self.^name))),
self.SET-SELF(
Rakudo::QuantHash.ADD-PAIRS-TO-SET(
nqp::create(Rakudo::Internals::IterationSet), iterator
nqp::create(Rakudo::Internals::IterationSet),iterator,self.keyof
)
)
)
Expand Down Expand Up @@ -222,12 +228,12 @@ my class SetHash does Setty {
nqp::stmts(
nqp::unless(
$!elems,
# XXX for some reason, $!elems := nqp::create(...) doesn't work
# Type check failed in binding; expected NQPMu but got Rakudo::Internals::IterationSet
nqp::bindattr(self,::?CLASS,'$!elems',
nqp::create(Rakudo::Internals::IterationSet))
),
nqp::bindkey($!elems,k.WHICH,nqp::decont(k))
Rakudo::QuantHash.BIND-TO-TYPED-SET(
$!elems, nqp::decont(k), self.keyof
)
),
$!elems && nqp::deletekey($!elems,k.WHICH)
),
Expand Down
16 changes: 8 additions & 8 deletions src/core/Setty.pm6
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
my role Setty[::CONSTRAINT = Mu] does QuantHash[CONSTRAINT] {
my role Setty does QuantHash {
has Rakudo::Internals::IterationSet $!elems; # key.WHICH => key

method of() { Bool }

# helper sub to create Set from iterator, check for laziness
sub create-from-iterator(\type, \iterator --> Setty:D) {
# private method to create Set from iterator, check for laziness
method !create-from-iterator(\type, \iterator --> Setty:D) {
nqp::if(
iterator.is-lazy,
Failure.new(X::Cannot::Lazy.new(:action<coerce>,:what(type.^name))),
nqp::create(type).SET-SELF(
Rakudo::QuantHash.ADD-ITERATOR-TO-SET(
nqp::create(Rakudo::Internals::IterationSet), iterator
nqp::create(Rakudo::Internals::IterationSet),iterator,self.keyof
)
)
)
Expand All @@ -20,7 +20,7 @@ my role Setty[::CONSTRAINT = Mu] does QuantHash[CONSTRAINT] {
multi method new(Setty: \value --> Setty:D) {
nqp::if(
nqp::istype(value,Iterable) && nqp::not_i(nqp::iscont(value)),
create-from-iterator(self, value.iterator),
self!create-from-iterator(self, value.iterator),
nqp::stmts(
nqp::bindkey(
(my $elems := nqp::create(Rakudo::Internals::IterationSet)),
Expand All @@ -32,16 +32,16 @@ my role Setty[::CONSTRAINT = Mu] does QuantHash[CONSTRAINT] {
)
}
multi method new(Setty: **@args --> Setty:D) {
create-from-iterator(self, @args.iterator)
self!create-from-iterator(self, @args.iterator)
}

method new-from-pairs(*@pairs --> Setty:D) {
nqp::if(
(my $iterator := @pairs.iterator).is-lazy,
(my \iterator := @pairs.iterator).is-lazy,
Failure.new(X::Cannot::Lazy.new(:action<coerce>,:what(self.^name))),
nqp::create(self).SET-SELF(
Rakudo::QuantHash.ADD-PAIRS-TO-SET(
nqp::create(Rakudo::Internals::IterationSet), $iterator
nqp::create(Rakudo::Internals::IterationSet),iterator,self.keyof
)
)
)
Expand Down
6 changes: 4 additions & 2 deletions src/core/set_union.pm6
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,11 @@ multi sub infix:<(|)>(Iterable:D $a, Iterable:D $b) {
Rakudo::QuantHash.ADD-PAIRS-TO-SET(
Rakudo::QuantHash.ADD-PAIRS-TO-SET(
nqp::create(Rakudo::Internals::IterationSet),
$aiterator
$aiterator,
Mu
),
$biterator
$biterator,
Mu
)
)
)
Expand Down

0 comments on commit 4bb5c33

Please sign in to comment.