-
-
Notifications
You must be signed in to change notification settings - Fork 373
/
Enumeration.pm
86 lines (74 loc) · 2.02 KB
/
Enumeration.pm
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
# Method that we have on enumeration types.
my role Enumeration {
has $.key;
has $.value;
multi method Numeric(::?CLASS:D:) { $!value.Numeric }
method enums() {
self.^enum_values
}
multi method gist(::?CLASS:D:) {
$!key
}
method kv(::?CLASS:D:) { ($!key, $!value) }
method pair(::?CLASS:D:) { $!key => $!value }
method perl() {
self.defined ??
(self.^name ~ '::' ~ $!key) !!
self.^name;
}
method pick(*@pos, *%named) {
self.^enum_value_list.pick(|@pos, |%named)
}
method roll(*@pos, *%named) {
self.^enum_value_list.roll(|@pos, |%named)
}
method Int(::?CLASS:D:) {
self.value.Int
}
method postcircumfix:<( )>($ ($x)) {
$x ~~ ::?CLASS ?? $x !! self.^enum_from_value($x)
}
}
# Methods that we also have if the base type of an enumeration is
# Numeric.
my role NumericEnumeration {
multi method Str(::?CLASS:D:) {
self.key
}
}
my role StringyEnumeration {
multi method Str(::?CLASS:D:) {
self.value
}
}
sub ANON_ENUM(*@args) {
my Mu $prev = -1;
my %res;
for @args {
if .^isa(Enum) {
%res{.key} = .value;
}
else {
%res{$_} = $prev.=succ;
}
}
my $r := nqp::create(EnumMap);
nqp::bindattr($r, EnumMap, '$!storage',
nqp::getattr(%res, EnumMap, '$!storage'));
$r;
}
Metamodel::EnumHOW.set_composalizer(-> $type, $name, %enum_values {
my Mu $r := Metamodel::ParametricRoleHOW.new_type(:name($name));
$r.HOW.add_attribute($r, Attribute.new(
:name('$!' ~ $name), :type(nqp::decont($type)),
:has_accessor(1), :package($r)));
for %enum_values.kv -> $key, $value {
my $meth = method () { self."$name"() === $value }
$meth.set_name($key);
$r.HOW.add_method($r, $key, $meth);
}
$r.HOW.set_body_block($r,
-> |c { nqp::list($r, nqp::hash('$?CLASS', c<$?CLASS>)) });
$r.HOW.compose($r);
$r
});