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'