-
-
Notifications
You must be signed in to change notification settings - Fork 373
/
EnumHOW.nqp
183 lines (152 loc) Β· 5.36 KB
/
EnumHOW.nqp
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# This is the meta-object for an enumeration (declared with enum).
# It keeps hold of the enumeration values in an Map, which is
# created at composition time. It supports having roles composed in,
# one or two of which presumably provide the core enum-ish methods.
class Perl6::Metamodel::EnumHOW
does Perl6::Metamodel::Naming
does Perl6::Metamodel::Documenting
does Perl6::Metamodel::Stashing
does Perl6::Metamodel::AttributeContainer
does Perl6::Metamodel::MethodContainer
does Perl6::Metamodel::PrivateMethodContainer
does Perl6::Metamodel::MultiMethodContainer
does Perl6::Metamodel::RoleContainer
does Perl6::Metamodel::BaseType
does Perl6::Metamodel::MROBasedMethodDispatch
does Perl6::Metamodel::MROBasedTypeChecking
does Perl6::Metamodel::BUILDPLAN
does Perl6::Metamodel::BoolificationProtocol
does Perl6::Metamodel::REPRComposeProtocol
does Perl6::Metamodel::InvocationProtocol
does Perl6::Metamodel::Mixins
{
# Hash representing enumeration keys to values.
has %!values;
# Reverse mapping hash.
has %!value_to_enum;
# List of enum values (actual enum objects).
has @!enum_value_list;
# Roles that we do.
has @!role_typecheck_list;
# Role'd version of the enum.
has $!role;
has int $!roled;
# Are we composed yet?
has $!composed;
# Exportation callback for enum symbols, if any.
has $!export_callback;
my $archetypes := Perl6::Metamodel::Archetypes.new( :nominal(1), :composalizable(1),
:augmentable(1) );
method archetypes() {
$archetypes
}
method new(*%named) {
nqp::findmethod(NQPMu, 'BUILDALL')(nqp::create(self), |%named)
}
method new_type(:$name!, :$base_type?, :$repr = 'P6opaque', :$is_mixin) {
my $meta := self.new();
my $obj := nqp::settypehll(nqp::newmixintype($meta, $repr), 'perl6');
$meta.set_name($obj, $name);
$meta.set_base_type($meta, $base_type) unless $base_type =:= NQPMu;
$meta.setup_mixin_cache($obj);
self.add_stash($obj);
}
# We only have add_parent to support mixins, which expect this method.
method add_parent($obj, $parent) {
self.set_base_type($obj, $parent);
}
method add_enum_value($obj, $value) {
%!values{nqp::unbox_s($value.key)} := $value.value;
@!enum_value_list[+@!enum_value_list] := $value;
}
method set_export_callback($obj, $callback) {
$!export_callback := $callback
}
method enum_values($obj) {
%!values
}
method elems($obj) {
nqp::elems(%!values)
}
method enum_from_value($obj, $value) {
unless %!value_to_enum {
for @!enum_value_list {
%!value_to_enum{$_.value} := $_;
}
}
nqp::existskey(%!value_to_enum, $value)
?? %!value_to_enum{$value}
!! $obj.WHAT;
}
method enum_value_list($obj) {
@!enum_value_list
}
method compose($the-obj, :$compiler_services) {
my $obj := nqp::decont($the-obj);
# Instantiate all of the roles we have (need to do this since
# all roles are generic on ::?CLASS) and pass them to the
# composer.
my @roles_to_compose := self.roles_to_compose($obj);
if @roles_to_compose {
my @ins_roles;
while @roles_to_compose {
my $r := @roles_to_compose.pop();
@!role_typecheck_list[+@!role_typecheck_list] := $r;
@ins_roles.push($r.HOW.specialize($r, $obj))
}
RoleToClassApplier.apply($obj, @ins_roles);
# Add them to the typecheck list, and pull in their
# own type check lists also.
for @ins_roles {
@!role_typecheck_list[+@!role_typecheck_list] := $_;
for $_.HOW.role_typecheck_list($_) {
@!role_typecheck_list[+@!role_typecheck_list] := $_;
}
}
}
# Incorporate any new multi candidates (needs MRO built).
self.incorporate_multi_candidates($obj);
# Compose attributes.
for self.attributes($obj, :local) {
$_.compose($obj);
}
# Publish type and method caches.
self.publish_type_cache($obj);
self.publish_method_cache($obj);
# Publish boolification spec.
self.publish_boolification_spec($obj);
# Create BUILDPLAN.
self.create_BUILDPLAN($obj);
# Compose the representation.
unless $!composed {
self.compose_repr($obj);
$!composed := 1;
}
# Compose invocation protocol.
self.compose_invocation($obj);
$obj
}
# Called by the compiler when all enum values have been added, to trigger
# any needed actions.
method compose_values($obj) {
if $!export_callback {
$!export_callback();
$!export_callback := Mu;
}
}
my $composalizer;
method set_composalizer($c) { $composalizer := $c }
method composalize($obj) {
unless $!roled {
$!role := $composalizer($obj, self.name($obj), %!values);
$!roled := 1;
}
$!role
}
method is_composed($obj) {
$!composed
}
method role_typecheck_list($obj) {
@!role_typecheck_list
}
}