-
-
Notifications
You must be signed in to change notification settings - Fork 372
/
Mixy.pm6
148 lines (137 loc) Β· 5.05 KB
/
Mixy.pm6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
my role Mixy does Baggy {
method of(--> Real) { }
multi method hash(Mixy:D: --> Hash:D) { self!HASHIFY(Real) }
multi method Hash(Mixy:D: --> Hash:D) { self!HASHIFY(Any) }
multi method kxxv(Mixy:D:) {
Failure.new(".kxxv is not supported on a {self.^name}")
}
multi method grab(Mixy:D: $count?) {
Failure.new(".grab is not supported on a {self.^name}")
}
multi method pick(Mixy:D: $count?) {
Failure.new(".pick is not supported on a {self.^name}, maybe use .roll instead?")
}
multi method roll(Mixy:D:) {
(my \raw := self.RAW-HASH) && (my \total := self!total-positive)
?? nqp::getattr(
nqp::iterval(Rakudo::QuantHash.MIX-ROLL(raw,total)),Pair,'$!key'
)
!! Nil
}
multi method roll(Mixy:D: Whatever) {
Seq.new(
(my \raw := self.RAW-HASH) && (my \total := self!total-positive)
?? Rakudo::Iterator.Callable( {
nqp::getattr(
nqp::iterval(Rakudo::QuantHash.MIX-ROLL(raw,total)),
Pair,
'$!key'
)
}, True )
!! Rakudo::Iterator.Empty
)
}
multi method roll(Mixy:D: Callable:D $calculate) {
(my $total := self!total-positive)
?? self.roll($calculate($total))
!! Seq.new(Rakudo::Iterator.Empty)
}
multi method roll(Mixy:D: $count) {
$count == Inf
?? self.roll(*) # let Whatever handle it
!! Seq.new( # something else as count
(my $todo = $count.Int) < 1 # also handles NaN
?? Rakudo::Iterator.Empty # nothing to do
!! (my \raw := self.RAW-HASH)
&& (my \total := self!total-positive)
&& ++$todo
?? Rakudo::Iterator.Callable( { # need to do a number of times
--$todo
?? nqp::getattr(
nqp::iterval(
Rakudo::QuantHash.MIX-ROLL(raw,total)
),
Pair,
'$!key'
)
!! IterationEnd
} )
!! Rakudo::Iterator.Empty # nothing to roll for
)
}
#--- object creation methods
method new-from-pairs(Mixy:_: *@pairs --> Mixy:D) {
(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-MIX(
nqp::create(Rakudo::Internals::IterationSet),
iterator,
self.keyof
)
)
}
#--- coercion methods
sub SETIFY(\mixy, \type) {
nqp::if(
(my \raw := mixy.RAW-HASH) && nqp::elems(raw),
nqp::stmts(
(my \elems := nqp::clone(raw)),
(my \iter := nqp::iterator(elems)),
nqp::while(
iter,
nqp::if(
nqp::getattr(nqp::iterval(nqp::shift(iter)),Pair,'$!value') < 0,
nqp::deletekey(elems,nqp::iterkey_s(iter)),
nqp::bindkey(
elems,
nqp::iterkey_s(iter),
nqp::getattr(nqp::iterval(iter),Pair,'$!key')
)
)
),
nqp::create(type).SET-SELF(elems)
),
nqp::if(
nqp::eqaddr(type,Set),
set(),
nqp::create(type)
)
)
}
multi method Set(Mixy:D:) { SETIFY(self,Set) }
multi method SetHash(Mixy:D:) { SETIFY(self,SetHash) }
sub BAGGIFY(\mixy, \type) {
nqp::if(
(my \raw := mixy.RAW-HASH) && nqp::elems(raw),
nqp::stmts( # something to coerce
(my \elems := nqp::clone(raw)),
(my \iter := nqp::iterator(elems)),
nqp::while(
iter,
nqp::if(
(my \value := nqp::getattr(
nqp::iterval(nqp::shift(iter)),Pair,'$!value'
).Int) > 0, # .Int also deconts
nqp::bindkey( # ok to keep value.Int
elems,
nqp::iterkey_s(iter),
nqp::p6bindattrinvres(
nqp::iterval(iter),Pair,'$!value',value)
),
nqp::deletekey(elems,nqp::iterkey_s(iter))
)
),
nqp::create(type).SET-SELF(elems),
),
nqp::if( # nothing to coerce
nqp::istype(type,Bag),
bag(),
nqp::create(BagHash)
)
)
}
multi method Bag(Baggy:D:) { BAGGIFY(self, Bag) }
multi method BagHash(Baggy:D:) { BAGGIFY(self, BagHash) }
}
# vim: expandtab shiftwidth=4