Skip to content

Commit 3245496

Browse files
committed
Allow ::($foo) for methods inside roles.
Again, a fairly restricted form, but sufficient for what NQP needs to provide for Rakudo to do user defined ops as role mixins.
1 parent 964e007 commit 3245496

File tree

4 files changed

+45
-9
lines changed

4 files changed

+45
-9
lines changed

src/NQP/Actions.pm

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ class NQP::Actions is HLL::Actions {
609609
}
610610
}
611611
$past.unshift($params);
612+
$past.push(QAST::Op.new( :op('curlexpad') ));
612613
$past.symbol('$?CLASS', :scope('lexical'));
613614
$*W.pkg_set_body_block($*PACKAGE, $past);
614615
$*W.install_lexical_symbol($past, '$?PACKAGE', $*PACKAGE);
@@ -935,9 +936,18 @@ class NQP::Actions is HLL::Actions {
935936
$past.symbol('self', :scope('lexical') );
936937

937938
# Install it where it should go (methods table / namespace).
939+
my $name := "";
938940
if $<deflongname> {
941+
$name := ~$<private> ~ ~$<deflongname>[0].ast;
942+
}
943+
elsif $<latename> {
944+
if $*PKGDECL ne 'role' {
945+
$/.CURSOR.panic("Late-bound method name only valid in role");
946+
}
947+
$name := "!!LATENAME!!" ~ ~$<latename>;
948+
}
949+
if $name ne "" {
939950
# Set name.
940-
my $name := ~$<private> ~ ~$<deflongname>[0].ast;
941951
$past.name($name);
942952

943953
# Insert it into the method table.
@@ -1133,7 +1143,16 @@ class NQP::Actions is HLL::Actions {
11331143
}
11341144

11351145
method regex_declarator($/, $key?) {
1136-
my $name := ~$<deflongname>.ast;
1146+
my $name;
1147+
if $<deflongname> {
1148+
$name := ~$<deflongname>.ast;
1149+
}
1150+
else {
1151+
if $*PKGDECL ne 'role' {
1152+
$/.CURSOR.panic("Late-bound method name only valid in role");
1153+
}
1154+
$name := "!!LATENAME!!" ~ ~$<latename>;
1155+
}
11371156
my $past;
11381157
if $<proto> {
11391158
$past :=

src/NQP/Grammar.pm

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,10 @@ grammar NQP::Grammar is HLL::Grammar {
470470
rule method_def {
471471
:my $*RETURN_USED := 0;
472472
:my $*INVOCANT_OK := 1;
473-
$<private>=['!'?]
474-
<deflongname>?
473+
[
474+
|| '::(' <latename=variable> ')'
475+
|| $<private>=['!'?] <deflongname>?
476+
]
475477
<.newpad>
476478
[ '(' <signature> ')'
477479
|| <.panic: 'Routine declaration requires a signature'> ]
@@ -539,22 +541,28 @@ grammar NQP::Grammar is HLL::Grammar {
539541
token regex_declarator {
540542
[
541543
| $<proto>=[proto] :s [regex|token|rule]
542-
<deflongname>
544+
[
545+
|| '::(' <latename=variable> ')'
546+
|| <deflongname>
547+
]
543548
[
544549
|| '{*}'<?ENDSTMT>
545550
|| '{' '<...>' '}'<?ENDSTMT>
546551
|| '{' '<*>' '}'<?ENDSTMT>
547552
|| <.panic: "Proto regex body must be \{*\} (or <*> or <...>, which are deprecated)">
548553
]
549554
| $<sym>=[regex|token|rule] :s
550-
<deflongname>
555+
[
556+
|| '::(' <latename=variable> ')'
557+
|| <deflongname>
558+
]
551559
<.newpad>
552560
[ '(' <signature> ')' ]?
553561
:my %*RX;
554562
{
555563
%*RX<s> := $<sym> eq 'rule';
556564
%*RX<r> := $<sym> eq 'token' || $<sym> eq 'rule';
557-
%*RX<name> := $<deflongname>.ast;
565+
%*RX<name> := $<deflongname>.ast if $<deflongname>;
558566
}
559567
'{'<p6regex=.LANG('Regex','nibbler')>'}'<?ENDSTMT>
560568
]

src/core/NQPRoutine.pm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ my knowhow NQPRoutine {
4848
method nqpattr($key) {
4949
$!do.nqpattr($key)
5050
}
51+
method !set_name($name) {
52+
pir::assign__0Ps($!do, $name);
53+
}
5154
}
5255
pir::stable_publish_vtable_handler_mapping__vPP(NQPRoutine,
5356
nqp::hash(

src/how/NQPParametricRoleHOW.pm

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ knowhow NQPParametricRoleHOW {
119119
method specialize($obj, $class_arg, *@args) {
120120
# Run the body block to capture the arguments into the correct
121121
# type argument context.
122-
$!body_block($class_arg, |@args);
122+
my $pad := $!body_block($class_arg, |@args);
123123

124124
# Construct a new concrete role.
125125
my $irole := NQPConcreteRoleHOW.new_type(:name($!name), :instance_of($obj));
@@ -132,7 +132,13 @@ knowhow NQPParametricRoleHOW {
132132

133133
# Capture methods in the correct lexical context.
134134
for %!methods {
135-
$irole.HOW.add_method($irole, $_.key, $_.value.clone());
135+
my $name := $_.key;
136+
my $meth := $_.value.clone();
137+
if nqp::substr($name, 0, 12) eq '!!LATENAME!!' {
138+
$name := nqp::atkey($pad, nqp::substr($name, 12));
139+
$meth.'!set_name'($name);
140+
}
141+
$irole.HOW.add_method($irole, $name, $meth);
136142
}
137143
for @!multi_methods_to_incorporate {
138144
$irole.HOW.add_multi_method($irole, $_<name>, reify_method($_<code>));

0 commit comments

Comments
 (0)