Skip to content

Commit ef939e0

Browse files
committed
Basic implementation of NQP dispatchers
For now, these don't take care of NQP's multiple dispatch.
1 parent d2c3437 commit ef939e0

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

src/core/NQPMu.nqp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ my class NQPMu {
9898
}
9999
}
100100

101-
# A few bits when we're bootstrapping everything 6model-style
101+
# An NQP array, which is the standard array representation with a few methods
102+
# added.
102103
my class NQPArray is repr('VMArray') {
103104
method push($value) { nqp::push(self, $value) }
104105
method pop() { nqp::pop(self) }
@@ -107,6 +108,8 @@ my class NQPArray is repr('VMArray') {
107108
}
108109
nqp::setboolspec(NQPArray, 8, nqp::null());
109110
nqp::settypehllrole(NQPArray, 4);
111+
112+
# Iterator types.
110113
my class NQPArrayIter is repr('VMIter') { }
111114
nqp::setboolspec(NQPArrayIter, 7, nqp::null());
112115
my class NQPHashIter is repr('VMIter') {
@@ -115,6 +118,8 @@ my class NQPHashIter is repr('VMIter') {
115118
method Str() { nqp::iterkey_s(self) }
116119
}
117120
nqp::setboolspec(NQPHashIter, 7, nqp::null());
121+
122+
# NQP HLL configuration.
118123
nqp::sethllconfig('nqp', nqp::hash(
119124
'list', NQPArray,
120125
'slurpy_array', NQPArray,
@@ -124,6 +129,10 @@ nqp::sethllconfig('nqp', nqp::hash(
124129
# BOOTHashes don't actually need transformation
125130
nqp::ishash($hash) ?? $hash !! $hash.FLATTENABLE_HASH
126131
},
132+
#?if moar
133+
'call_dispatcher', 'nqp-call',
134+
'call_method_dispatcher', 'nqp-meth-call',
135+
#?endif
127136
));
128137

129138
my class NQPLabel { }

src/core/dispatchers.nqp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#?if moar
2+
nqp::dispatch('boot-syscall', 'dispatcher-register', 'nqp-meth-call', -> $capture {
3+
# Try to find the method; complain if there's none found.
4+
my $obj := nqp::captureposarg($capture, 0);
5+
my str $name := nqp::captureposarg_s($capture, 1);
6+
my $meth := $obj.HOW.find_method($obj, $name);
7+
unless nqp::isconcrete($meth) {
8+
nqp::die("Method '$name' not found for invocant of class '{$obj.HOW.name($obj)}'");
9+
}
10+
11+
# Establish a guard on the invocant type and method name (however the name
12+
# may well be a literal, in which case this is free).
13+
nqp::dispatch('boot-syscall', 'dispatcher-guard-type',
14+
nqp::dispatch('boot-syscall', 'dispatcher-track-arg', $capture, 0));
15+
nqp::dispatch('boot-syscall', 'dispatcher-guard-literal',
16+
nqp::dispatch('boot-syscall', 'dispatcher-track-arg', $capture, 1));
17+
18+
# Drop the first two arguments, which are the decontainerized invocant
19+
# and the method name. Then insert the resolved method and delegate to
20+
# nqp-call to invoke it.
21+
my $args := nqp::dispatch('boot-syscall', 'dispatcher-drop-arg',
22+
nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $capture, 0),
23+
0);
24+
my $delegate := nqp::dispatch('boot-syscall', 'dispatcher-insert-arg-literal-obj',
25+
$args, 0, $meth);
26+
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'nqp-call', $delegate);
27+
});
28+
29+
nqp::dispatch('boot-syscall', 'dispatcher-register', 'nqp-call', -> $capture {
30+
# Guard on the type of the callee.
31+
my $track-callee := nqp::dispatch('boot-syscall', 'dispatcher-track-arg', $capture, 0);
32+
nqp::dispatch('boot-syscall', 'dispatcher-guard-type', $track-callee);
33+
34+
# Go by callee type to decide how to invoke it.
35+
my $callee := nqp::captureposarg($capture, 0);
36+
if nqp::istype($callee, NQPRoutine) {
37+
# Routine, maybe multi.
38+
# TODO multi
39+
my $track-do := nqp::dispatch('boot-syscall', 'dispatcher-track-attr',
40+
$track-callee, NQPRoutine, '$!do');
41+
my $args := nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $capture, 0);
42+
my $delegate := nqp::dispatch('boot-syscall', 'dispatcher-insert-arg',
43+
$args, 0, $track-do);
44+
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'boot-code-constant',
45+
$delegate);
46+
}
47+
elsif nqp::istype($callee, NQPRegex) {
48+
# Regex, just unwrap the code handle and delegate.
49+
my $track-do := nqp::dispatch('boot-syscall', 'dispatcher-track-attr',
50+
$track-callee, NQPRegex, '$!do');
51+
my $args := nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $capture, 0);
52+
my $delegate := nqp::dispatch('boot-syscall', 'dispatcher-insert-arg',
53+
$args, 0, $track-do);
54+
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'boot-code-constant',
55+
$delegate);
56+
}
57+
elsif nqp::iscoderef($callee) {
58+
# VM-level code handle.
59+
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'boot-code-constant',
60+
$capture);
61+
}
62+
else {
63+
nqp::die("Cannot invoke object of type '{$callee.HOW.name($callee)}'");
64+
}
65+
});
66+
#?endif

tools/templates/Makefile-common.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ CORE_SETTING_SOURCES = \
2222
@nfp(src/core/Hash.nqp)@ \
2323
@nfp(src/core/NQPLock.nqp)@ \
2424
@nfp(src/core/testing.nqp)@ \
25+
@nfp(src/core/dispatchers.nqp)@ \
2526
@nfp(src/core/YOUAREHERE.nqp)@ \
2627

2728
CORE_SETTING_COMBINED = NQPCORE.setting

0 commit comments

Comments
 (0)