Skip to content

Instantly share code, notes, and snippets.

@gfldex
Created July 13, 2022 23:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gfldex/235b56774bad982f30badbd6f234af69 to your computer and use it in GitHub Desktop.
Save gfldex/235b56774bad982f30badbd6f234af69 to your computer and use it in GitHub Desktop.
use v6.d;
role BitMask[@names] {
has uint64 $.mask;
sub names-to-bits(@a) {
my int $mask;
for @a -> $s {
$mask = $mask +| (1 +< @names.first($s, :k) // fail('bad‼'))
}
$mask
}
sub bits-to-names($mask) {
($mask.base(2).comb.reverse Z @names).map: -> [Int() $is-it, $name] { $is-it ?? $name !! Empty }
}
multi method COERCE(Str $s) { self.COERCE: $s.split(' ').list }
multi method COERCE(List $l) { self.new: :mask($l.&names-to-bits) }
method raku { "BitMask[<@names[]>](<{$!mask.&bits-to-names}>)" }
method bits(--> Str) { $.mask.fmt('%b') }
}
class C {
has BitMask[<ENODOC ENOSPEC LTA SEGV>]() $.attr is required;
}
# CATCH {
# when X::Coerce::Impossible && .target-type.HOW === Metamodel::CurriedRoleHOW {
# put "Sadly, COERCE has failed for {.from-type.^name}. Available candidates are: ", .target-type.new.^lookup('COERCE').candidates».signature».params[*;1]».type.map(*.^name)
# }
# }
my $c = C.new: :attr<ENODOC ENOSPEC SEGV>;
say $c;
say $c.attr.bits;
my $c2 = C.new: attr => 'ENODOC ENOSPEC SEGV';
say $c2;
enum IssueTypes ( ENODOC => 0b0001, ENOSPEC => 0b0010, LTA => 0b0100, SEGV => 0b1001 );
class IssueTypesBits does BitMask[<ENODOC ENOSPEC LTA SEGV>] {
method new(*@a where .all ~~ IssueTypes) {
self.bless: mask => [+|] @a
}
}
sub bitmask(*@a where .all ~~ IssueTypes) {
IssueTypesBits.new: |@a
}
my $c3 = C.new: attr => BEGIN bitmask(ENODOC, LTA, SEGV);
say $c3;
say $c3.attr.bits;
my $c4 = C.new: attr => 42;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment