Author: lwall
Date: 2009-03-13 00:15:48 +0100 (Fri, 13 Mar 2009)
New Revision: 25809

Modified:
   docs/Perl6/Spec/S02-bits.pod
   docs/Perl6/Spec/S03-operators.pod
   docs/Perl6/Spec/S04-control.pod
   docs/Perl6/Spec/S12-objects.pod
   src/perl6/STD.pm
   t/perl5/roundtrip.t
   t/spec/S02-literals/pairs.t
   t/spec/S02-literals/sub-calls.t
   t/spec/S12-methods/instance.t
   t/spec/S12-methods/syntax.t
Log:
[STD] special named forms foo() .foo() and $.foo() no longer support
the dereferencing .() postfix syntax, since they don't actually do
any dereferencing!  You may still insert space using "unspace" however.
This decrease in consistency on the syntactic level is offset by an
increase in consistency on the semantic level, as suggested by rouso++.
(We'd already gotten rid of the dot forms of adverbs some time ago,
for similar reasons.  We just didn't quite carry the idea through.)


Modified: docs/Perl6/Spec/S02-bits.pod
===================================================================
--- docs/Perl6/Spec/S02-bits.pod        2009-03-12 22:34:06 UTC (rev 25808)
+++ docs/Perl6/Spec/S02-bits.pod        2009-03-12 23:15:48 UTC (rev 25809)
@@ -1597,7 +1597,7 @@
 
 Unlike in Perl 5, the notation C<&foo> merely stands for the C<foo>
 function as a Code object without calling it.  You may call any Code
-object with parens after it (which may, of course, contain arguments):
+object by dereferencing it with parens (which may, of course, contain 
arguments):
 
     &foo($arg1, $arg2);
 
@@ -1613,6 +1613,29 @@
         embedded comment
     ].($arg1, $arg2);
 
+Note however that the parentheses around arguments in the "normal"
+named forms of function and method calls are not postfix operators, so do
+not allow the C<.()> form, because the dot is indicative of an actual
+dereferencing operation, which the named forms aren't doing.  You
+may, however, use "unspace" to install extra space before the parens
+in the forms:
+
+    foo()       # okay
+    foo\ ()     # okay
+    foo.()      # means foo().()
+
+    .foo()      # okay
+    .foo\ ()    # okay
+    .foo.()     # means .foo().()
+
+    $.foo()     # okay
+    $.foo\ ()   # okay
+    $.foo.()    # means $.foo().()
+
+If you I<do> use the dotty form on these special forms, it will
+assume you wanted to call the named form without arguments, and
+then dereference the result of that.
+
 =item *
 
 With multiple dispatch, C<&foo> may actually be the name of a set

Modified: docs/Perl6/Spec/S03-operators.pod
===================================================================
--- docs/Perl6/Spec/S03-operators.pod   2009-03-12 22:34:06 UTC (rev 25808)
+++ docs/Perl6/Spec/S03-operators.pod   2009-03-12 23:15:48 UTC (rev 25809)
@@ -2576,12 +2576,13 @@
 (except for postfix adverbs, which may follow the parentheses provided they
 would not attach to some other operator by the rules of precedence).
 
-Other than various forms of parentheses, all other postfixes are
+Other than parentheses, all other postfixes are
 disallowed immediately after a list operator, even if there are no
 arguments.  To add a postfix to an argumentless list operator you
 must write it as a function call with empty parentheses:
 
     foo.[]      # ILLEGAL
+    foo.()      # ILLEGAL
     foo++       # ILLEGAL
     foo().[]    # legal
     foo()++     # legal (if foo() is rw)
@@ -2613,7 +2614,7 @@
     say foo++;                          ILLEGAL, need parens
 
     say foo($bar+1),$baz                say(foo($bar+1), $baz);
-    say foo.($bar+1),$baz               say(foo($bar+1), $baz);
+    say foo.($bar+1),$baz               ILLEGAL, need space or parens
     say foo ($bar+1),$baz               say(foo($bar+1, $baz));
     say foo .($bar+1),$baz              say(foo($_.($bar+1), $baz));
 

Modified: docs/Perl6/Spec/S04-control.pod
===================================================================
--- docs/Perl6/Spec/S04-control.pod     2009-03-12 22:34:06 UTC (rev 25808)
+++ docs/Perl6/Spec/S04-control.pod     2009-03-12 23:15:48 UTC (rev 25809)
@@ -1193,8 +1193,8 @@
     $scalar = ($x);     # grouping parens because term expected
     if $term($x)        # function call because operator expected
     if $term ($x)       # syntax error (two terms in a row)
-    if $term.($x)       # valid function call with dot
-    if $term\ .($x)     # valid function call with "unspace"
+    if $term.($x)       # valid function call with explicit dot deref
+    if $term\ .($x)     # valid function call with "unspace" and dot
 
 Outside of any kind of expression brackets, a final closing curly
 on a line (not counting whitespace or comments) always reverts

Modified: docs/Perl6/Spec/S12-objects.pod
===================================================================
--- docs/Perl6/Spec/S12-objects.pod     2009-03-12 22:34:06 UTC (rev 25808)
+++ docs/Perl6/Spec/S12-objects.pod     2009-03-12 23:15:48 UTC (rev 25809)
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <la...@wall.org>
   Date: 27 Oct 2004
-  Last Modified: 9 Mar 2009
+  Last Modified: 12 Mar 2009
   Number: 12
-  Version: 75
+  Version: 76
 
 =head1 Overview
 
@@ -386,23 +386,27 @@
 Parentheses (or a colon) are required on the dot/bang notations if there
 are any arguments (not counting adverbial arguments).  There may be
 no space between the method name and the left parenthesis unless you
-use the dot form of parentheses or otherwise make use of "unspace":
+make use of "unspace":
 
     .doit       # okay, no arguments
     .doit()     # okay, no arguments
     .doit ()    # ILLEGAL (two terms in a row)
-    .doit.()    # okay, no arguments, same as .doit()
     .doit\ ()   # okay, no arguments, same as .doit() (unspace form)
-    .doit\ .()  # okay, no arguments, same as .doit.() (unspace form)
 
-However, you can turn any of the legal forms above into a list
+Note that the named method call forms are special and do not use the dot
+form of postfix.  If you attempt to use the postfix operator form, it
+will assume you want to call the method with no arguments and then call
+the result of I<that>:
+
+    .doit.()    # okay, no arguments *twice*, same as .doit().()
+    .doit\ .()  # okay, no arguments *twice*, same as .doit.().() (unspace 
form)
+
+However, you can turn any of the named forms above into a list
 operator by appending a colon:
 
     .doit: 1,2,3        # okay, three arguments
     .doit(1): 2,3       # okay, one argument plus list
     .doit (): 1,2,3     # ILLEGAL (two terms in a row)
-    .doit.(1): 2,3      # okay, same as .doit(1,2,3)
-    .doit\ .(1,2): 3    # okay, same as .doit(1,2,3)
 
 In particular, this allows us to pass a closure in addition to the
 "normal" arguments:
@@ -612,14 +616,16 @@
 any of those as an attribute -- a C<method foo> declaration can work
 just as well.
 
-The dot form can take an argument list as well.  These are all equivalent:
+As with the normal method call forms, only dotless parentheses may contain 
arguments.
+If you use the C<.()> form it will perform an extra level of indirection after
+the method call:
 
     self.foo(1,2,3);    # a regular method call
-    self.foo.(1,2,3);   # ditto
+    self.foo.(1,2,3);   # self.foo().(1,2,3), call .() on closure returned by 
.foo
     $.foo(1,2,3);       # calls self.foo under $ context
-    $.foo.(1,2,3);      # ditto
-    @.foo(1,2,3);       # calls self.foo under @ context
-    @.foo.(1,2,3);      # ditto
+    $.foo.(1,2,3);      # $.foo().(1,2,3), call .() on closure returned by .foo
+    &.foo(1,2,3);       # calls self.foo under & context
+    &.foo.(1,2,3);      # &.foo().(1,2,3), call .() on closure returned by .foo
 
 Pseudo-assignment to an attribute declaration specifies the default
 value.  The value on the right is treated as an implicit closure and
@@ -1466,7 +1472,8 @@
 Like type names, enum names are parsed as standalone tokens
 representing scalar values, and don't look for any arguments.
 Unlike type names which are undefined protoobjects, enums are defined
-constant values.  Also unlike types, they do not respond to C<.()>.
+constant values.  Also unlike types, they do not respond to C<.()>
+unless you mix in C<Callable> somehow.
 They may not be post-declared.
 
     our enum Maybe <OK FAIL>;
@@ -1474,7 +1481,7 @@
     $x = OK;   # certainly the enum value
     $x = OK()  # certainly the function
 
-Since there is an enum OK, the function OK may only be
+Since there is an enum C<OK>, the function C<OK> may only be
 called using parentheses, never in list operator form.  (If there is
 a collision on two enum values that cancels them both, the function
 still may only be called with parentheses, since the enum symbol

Modified: src/perl6/STD.pm
===================================================================
--- src/perl6/STD.pm    2009-03-12 22:34:06 UTC (rev 25808)
+++ src/perl6/STD.pm    2009-03-12 23:15:48 UTC (rev 25809)
@@ -1608,7 +1608,7 @@
     :dba('method arguments')
     [
     | ':' <?before \s> <!{ $*inquote }> <arglist>
-    | <?[.(]> <args>
+    | <?[\\(]> <args>
     ]?
 }
 
@@ -2118,10 +2118,12 @@
 
     { my $t = $<twigil>; $twigil = $t.[0].Str if @$t; }
     [ <?{ $twigil eq '.' }>
-        <.unsp>? <?before '('> <postcircumfix> {*}          #= methcall
+        [<.unsp> | '\\' | <?> ] <?before '('> <postcircumfix> {*}          #= 
methcall
     ]?
 }
 
+
+
 # Note, don't reduce on a bare sigil unless you don't want a twigil or
 # you otherwise don't care what the longest token is.
 
@@ -3822,7 +3824,7 @@
 {
     :my $name;
     :my $pos;
-    <identifier> <?before ['.'?'(']?>
+    <identifier> <?before [<unsp>|'(']? >
     { $name = $<identifier>.Str; $pos = $¢.pos; }
     <args( $¢.is_name($name) )>
     { self.add_mystery($name,$pos) unless $<args><invocant>; }
@@ -3839,9 +3841,9 @@
     :my $INVOCANT_OK is context<rw> = 1;
     :my $INVOCANT_IS is context<rw>;
     [
-    | :dba('argument list') '.(' ~ ')' <semiarglist> {*}             #= func 
args
+#    | :dba('argument list') '.(' ~ ')' <semiarglist> {*}             #= func 
args
     | :dba('argument list') '(' ~ ')' <semiarglist> {*}              #= func 
args
-    | :dba('argument list') <.unsp> '.'? '(' ~ ')' <semiarglist> {*} #= func 
args
+    | :dba('argument list') <.unsp> '(' ~ ')' <semiarglist> {*} #= func args
     |  { $listopish = 1 } [<?before \s> <!{ $istype }> <.ws> <!infixstopper> 
<arglist>]?
     ]
     { $<invocant> = $*INVOCANT_IS; }

Modified: t/perl5/roundtrip.t
===================================================================
--- t/perl5/roundtrip.t 2009-03-12 22:34:06 UTC (rev 25808)
+++ t/perl5/roundtrip.t 2009-03-12 23:15:48 UTC (rev 25809)
@@ -25,8 +25,8 @@
 my $japh2   = -> $name { "Just another $name hacker" };
 my $id      = eval('sub { Id->new($_[0]) }', :lang<perl5>);
 
-is($id($japh).identity.('Pugs'), 'Just another Pugs hacker', "Closure 
roundtrips");
-is($id($japh2).identity.('Pugs'), 'Just another Pugs hacker', "Closure 
roundtrips");
+is($id($japh).identity('Pugs'), 'Just another Pugs hacker', "Closure 
roundtrips");
+is($id($japh2).identity('Pugs'), 'Just another Pugs hacker', "Closure 
roundtrips");
 
 my $keys_p5 = eval('sub {keys %{$_[0]}}', :lang<perl5>);
 my $tohash_p5 = eval('sub { return {map {$_ => 1} @_ } }', :lang<perl5>);

Modified: t/spec/S02-literals/pairs.t
===================================================================
--- t/spec/S02-literals/pairs.t 2009-03-12 22:34:06 UTC (rev 25808)
+++ t/spec/S02-literals/pairs.t 2009-03-12 23:15:48 UTC (rev 25809)
@@ -50,7 +50,7 @@
     is f2(:a(42)),      "Int", "':a(42)' is a named";
     is f2(:a),          "Int", "':a' is a named";
 
-    is(f2.(:a),         "Int",  "in 'f2.(:a)', ':a' is a named");
+    is(&f2.(:a),         "Int",  "in '&f2.(:a)', ':a' is a named");
     is $f2(:a),         "Int",  "in '\$f2(:a)', ':a' is a named";
     is $f2.(:a),        "Int",  "in '\$f2.(:a)', ':a' is a named";
 
@@ -61,7 +61,7 @@
     dies_ok { f2(("a" => 42)) }, "'(\"a\" => 42)' is a pair";
     dies_ok { f2((:a(42)))    }, "'(:a(42))' is a pair";
     dies_ok { f2((:a))        }, "'(:a)' is a pair";
-    dies_ok { f2.((:a))       }, "in 'f2.((:a))', '(:a)' is a pair";
+    dies_ok { &f2.((:a))       }, "in '&f2.((:a))', '(:a)' is a pair";
     
     #?rakudo 4 todo 'not every pair acts as named parameters'
     dies_ok { $f2((:a))       }, "in '\$f2((:a))', '(:a)' is a pair";

Modified: t/spec/S02-literals/sub-calls.t
===================================================================
--- t/spec/S02-literals/sub-calls.t     2009-03-12 22:34:06 UTC (rev 25808)
+++ t/spec/S02-literals/sub-calls.t     2009-03-12 23:15:48 UTC (rev 25809)
@@ -23,13 +23,13 @@
 
     eval_lives_ok q/foo;      /, 'call with no args, no parens';
     eval_lives_ok q/foo();    /, 'call with no args, has parens';
-    eval_lives_ok q/foo.();   /, 'call with no args, has dot and parens';
-    eval_lives_ok q/foo\ .(); /, 'call with no args, has long dot and parens';
+    eval_lives_ok q/&foo.();   /, 'call with no args, has dot and parens';
+    eval_lives_ok q/&foo\ .(); /, 'call with no args, has long dot and parens';
 
     eval_lives_ok q/foo 1;    /, 'call with one arg, no parens';
     eval_lives_ok q/foo(1);   /, 'call with one arg, has parens';
-    eval_lives_ok q/foo.(1);  /, 'call with one arg, has dot and parens';
-    eval_lives_ok q/foo\ .(1);/, 'call with one arg, has long dot and parens';
+    eval_lives_ok q/&foo.(1);  /, 'call with one arg, has dot and parens';
+    eval_lives_ok q/&foo\ .(1);/, 'call with one arg, has long dot and parens';
     #?pugs todo 'unspecced'
     #?rakudo todo 'unspecced'
     eval_lives_ok q/foo'bar'; /, 'call with one arg, has no space and no 
parens';
@@ -42,9 +42,9 @@
     eval_lives_ok q/foo :bar; /, 'call with adverb after space';
 
     eval_lives_ok q/foo(:bar);  /, 'call with adverb in parens';
-    eval_lives_ok q/foo.(:bar); /, 'call with adverb in dotted-parens';
+    eval_lives_ok q/&foo.(:bar); /, 'call with adverb in dotted-parens';
     #?rakudo todo 'long dot'
-    eval_lives_ok q/foo\.(:bar);/, 'call with adverb in long-dotted parens';
+    eval_lives_ok q/&foo\.(:bar);/, 'call with adverb in long-dotted parens';
 }
 
 

Modified: t/spec/S12-methods/instance.t
===================================================================
--- t/spec/S12-methods/instance.t       2009-03-12 22:34:06 UTC (rev 25808)
+++ t/spec/S12-methods/instance.t       2009-03-12 23:15:48 UTC (rev 25809)
@@ -2,7 +2,7 @@
 
 use Test;
 
-plan 28;
+plan 26;
 
 =begin pod
 
@@ -39,22 +39,6 @@
 
 {
     my $val;
-    lives_ok {
-        $val = $foo.noargs.();
-    }, "... '.' + parentheses after method", :todo<bug>;
-    is($val, 42, '... we got the value correctly', :todo<feature>);
-}
-
-{
-    my $val;
-    lives_ok {
-        $val = $foo.noargs\ .();
-    }, "... <unspace> + '.' + parentheses after method", :todo<bug>;
-    is($val, 42, '... we got the value correctly', :todo<feature>);
-}
-
-{
-    my $val;
     lives_ok { $val = $foo.nobrackets() }, 'method declared with no brackets';
     is($val, 'mice', '... we got the value correctly');
 }

Modified: t/spec/S12-methods/syntax.t
===================================================================
--- t/spec/S12-methods/syntax.t 2009-03-12 22:34:06 UTC (rev 25808)
+++ t/spec/S12-methods/syntax.t 2009-03-12 23:15:48 UTC (rev 25809)
@@ -1,7 +1,7 @@
 use v6;
 use Test;
 
-plan 13;
+plan 10;
 
 # L<S12/Methods/"no space between the method name and the left parenthesis">
 
@@ -16,18 +16,15 @@
 
 is .doit,       'empty',        'plain call with no args';
 is .doit(),     'empty',        'method call with parens and no args';
-is .doit.(),    'empty',        'method call with dot-parens and no args';
 eval_dies_ok '.doit ()',        '.doit () illegal';
 is .doit\ (),   'empty',        'method call with unspace';
-is .doit\ .(),  'empty',        'method call with dotty unspace';
 
 is (.doit: 1, 2, 3),    'a:1|b:2!3',    'list op with colon';
 is (.doit: 1, 2, 3, 4), 'a:1|b:2!3!4',  'list op with colon, slurpy';
-#?rakudo 4 skip 'adverbial listop form'
+#?rakudo 3 skip 'switch-from-paren-to-listop form'
 is (.doit(1): 2, 3),    'a:1|b:2!3',    'list op with colon';
 is (.doit(1, 2): 3),    'a:1|b:2!3',    'list op with colon';
 is (.doit\  (1, 2): 3), 'a:1|b:2!3',    'list op with colon, unspace';
-is (.doit\ .(1, 2): 3), 'a:1|b:2!3',    'list op with colon, dotty unspace';
 
 # L<S12/Methods/"if any term in a list is a bare closure">
 #?rakudo skip 'adverbial closures'

Reply via email to