/
NQPMu.nqp
129 lines (117 loc) · 4.52 KB
/
NQPMu.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
my class NQPMu {
method CREATE() {
nqp::create(self)
}
method bless(NQPMu:U $self: *%attributes) {
my $instance := self.CREATE();
$instance.BUILDALL(|%attributes);
$instance
}
method BUILDALL(NQPMu:D $self: *%attrinit) {
# Get the build plan.
my $build_plan := self.HOW.BUILDALLPLAN(self);
my int $count := nqp::elems($build_plan);
my int $i := 0;
while $i < $count {
my $task := nqp::atpos($build_plan, $i);
$i := $i + 1;
# Something with data
if nqp::islist($task) {
my int $code := nqp::atpos($task, 0);
if nqp::iseq_i($code, 0) {
# See if we have a value to initialize this attr with.
my $key_name := nqp::atpos($task, 3);
if nqp::existskey(%attrinit, $key_name) {
nqp::bindattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2), %attrinit{$key_name});
}
}
elsif nqp::iseq_i($code, 4) {
unless nqp::attrinited(self, nqp::atpos($task, 1), nqp::atpos($task, 2)) {
nqp::bindattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2),
nqp::atpos($task, 3)(self,
nqp::getattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2))));
}
}
elsif nqp::iseq_i($code, 10) {
# Defeat lazy allocation
nqp::getattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2))
}
elsif nqp::iseq_i($code, 11) {
# See if we have a value to initialize this attr with;
# if not, set it to an empty array.
my $key_name := nqp::atpos($task, 3);
if nqp::existskey(%attrinit, $key_name) {
nqp::bindattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2), %attrinit{$key_name});
}
else {
nqp::bindattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2), nqp::list());
}
}
elsif nqp::iseq_i($code, 12) {
# See if we have a value to initialize this attr with;
# if not, set it to an empty array.
my $key_name := nqp::atpos($task, 3);
if nqp::existskey(%attrinit, $key_name) {
nqp::bindattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2), %attrinit{$key_name});
}
else {
nqp::bindattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2), nqp::hash());
}
}
else {
nqp::die("Invalid BUILDALLPLAN");
}
}
# Custom BUILD call.
else {
$task(self, |%attrinit);
}
}
self
}
method new(*%attributes) {
self.bless(|%attributes);
}
method defined() {
nqp::isconcrete(self)
}
proto method ACCEPTS($topic) { * }
multi method ACCEPTS(NQPMu:U $self: $topic) {
nqp::istype($topic, self.WHAT)
}
proto method NOT-ACCEPTS($topic) { * }
multi method NOT-ACCEPTS(NQPMu:U $self: $topic) {
nqp::isfalse(nqp::istype($topic, self.WHAT))
}
method isa($type) {
self.HOW.isa(self, $type)
}
}
# A few bits when we're bootstrapping everything 6model-style
my class NQPArray is repr('VMArray') {
method push($value) { nqp::push(self, $value) }
method pop() { nqp::pop(self) }
method unshift($value) { nqp::unshift(self, $value) }
method shift() { nqp::shift(self) }
}
nqp::setboolspec(NQPArray, 8, nqp::null());
nqp::settypehllrole(NQPArray, 4);
my class NQPArrayIter is repr('VMIter') { }
nqp::setboolspec(NQPArrayIter, 7, nqp::null());
my class NQPHashIter is repr('VMIter') {
method key() { nqp::iterkey_s(self) }
method value() { nqp::iterval(self) }
method Str() { nqp::iterkey_s(self) }
}
nqp::setboolspec(NQPHashIter, 7, nqp::null());
nqp::sethllconfig('nqp', nqp::hash(
'list', NQPArray,
'slurpy_array', NQPArray,
'array_iter', NQPArrayIter,
'hash_iter', NQPHashIter,
'foreign_transform_hash', -> $hash {
# BOOTHashes don't actually need transformation
nqp::ishash($hash) ?? $hash !! $hash.FLATTENABLE_HASH
},
));
my class NQPLabel { }