Author: lwall
Date: 2009-01-26 05:06:43 +0100 (Mon, 26 Jan 2009)
New Revision: 25031

Modified:
   docs/Perl6/Spec/S03-operators.pod
   src/perl6/Cursor.pmc
   src/perl6/STD.pm
   t/spec/S02-names_and_variables/names.t
   t/spec/S29-hash/exists.t
Log:
[STD, S03] more operator alignment and cleanup


Modified: docs/Perl6/Spec/S03-operators.pod
===================================================================
--- docs/Perl6/Spec/S03-operators.pod   2009-01-26 01:45:30 UTC (rev 25030)
+++ docs/Perl6/Spec/S03-operators.pod   2009-01-26 04:06:43 UTC (rev 25031)
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <la...@wall.org>
   Date: 8 Mar 2004
-  Last Modified: 13 Jan 2009
+  Last Modified: 24 Jan 2009
   Number: 3
-  Version: 148
+  Version: 149
 
 =head1 Overview
 
@@ -33,7 +33,7 @@
     L  Method postfix    .meth .+ .? .* .() .[] .{} .<> .«» .:: .= .^ .:
     N  Autoincrement     ++ --
     R  Exponentiation    **
-    L  Symbolic unary    ! + - ~ ? | +^ ~^ ?^ \ ^ =
+    L  Symbolic unary    ! + - ~ ? | +^ ~^ ?^ ^ =
     L  Multiplicative    * / % +& +< +> ~& ~< ~> ?& div mod
     L  Additive          + - +| +^ ~| ~^ ?| ?^
     L  Replication       x xx
@@ -48,9 +48,9 @@
     R  Conditional       ?? !! ff fff
     R  Item assignment   = := ::= => += -= **= xx= .=
     L  Loose unary       true not :by(2)
-    X  Comma operator    , p5=>
+    X  Comma operator    , p5=> :
     X  List infix        Z minmax X X~X X*X XeqvX ...
-    R  List prefix       : print push say die map substr ... [+] [*] any $ @
+    R  List prefix       print push say die map substr ... [+] [*] any $ @
     X  Loose and         and andthen
     X  Loose or          or xor orelse
     X  Sequencer         <==, ==>, <<==, ==>>
@@ -82,7 +82,7 @@
 
 Note that list associativity (X) only works between identical operators.
 If two different list-associative operators have the same precedence,
-they are assumed to be left-associative with respect to each other.
+they are assumed to be right-associative with respect to each other.
 For example, the C<X> cross operator and the C<Z> zip operator both
 have a precedence of "list infix", but:
 
@@ -90,10 +90,10 @@
 
 is parsed as:
 
-    (@a X @b) Z @c
+    @a X (@b Z @c)
 
 Similarly, if the only implementation of a list-associative operator
-is binary, it will be treated as left associative.
+is binary, it will be treated as right associative.
 
 If you don't see your favorite operator above, the following
 sections cover all the operators in precedence order.  Basic operator
@@ -669,18 +669,6 @@
 
 =item *
 
-C<< prefix:<\> >>, Capture constructor
-
-    \$x
-    \...@x
-    \%x
-    \($invocant: $pos1, $pos2, :named($arg))
-
-Defers the contextualization of its argument or arguments till it is
-bound into some other context.
-
-=item *
-
 C<< prefix:<^> >>, upto operator
 
     ^$limit
@@ -1557,6 +1545,71 @@
 explicitly if there is an explicit signature, or pull them out of C<%_>
 rather than C<@_> if there is no explicit signature.
 
+=item *
+
+C<< infix:<:> >>, the invocant marker
+
+    say $*OUT: "howdy, world"
+    say($*OUT: "howdy, world")
+    push @array: 1,2,3
+    push(@array: 1,2,3)
+    \($object: 1,2,3, :foo, :!bar)
+
+The colon operator parses just like a comma, but marks the argument to its 
left as an
+invocant, which has the effect of turning what would otherwise be a function
+call into a method call.  It may only be used on the first argument of
+an argument list or capture, and will fail to parse if used in any other 
position.
+When used within a capture, it is not yet know what signature the capture will
+be bound to; if bound to a non-method's signature, the invocant merely turns
+into the first positional argument, as if the colon had been a comma.
+
+To avoid confusion with other colon forms, the colon infix operator
+must be followed by whitespace or a terminator.  It may optionally
+have whitespace in front of it.
+
+Note: distinguish this infix operator from the colon in
+
+    @array.push: 1,2,3
+    @array.push(1,2,3): 4,5,6
+    push(@array, 1,2,3): 4,5,6
+
+which is a special form that turns an ordinary function or method
+call into a list operator.  The special form is recognized only after
+a dotty method call, or after the right parenthesis of a method or
+function call.  The special form does not allow intervening whitespace,
+but requires whitespace before the next argument.  In all other
+cases a colon will be parsed as the start of an adverb if possible,
+or otherwise the invocant marker (the infix described above).
+
+Another way to think of it is that the special colon is allowed to
+add listop arguments to a parenthesized argument list only after
+the right parenthesis of that argument list, with the proviso that
+you're allowed to shorten C<.foo(): 1,2,3> down to C<.foo: 1,2,3>.
+(But only for method calls, since ordinary functions don't need the
+colon in the first place to turn into a listop, just whitespace.
+If you try to extend a function name with a colon, it's likely
+to be taken as a label.)
+
+    foo $obj.bar: 1,2,3     # special, means foo($obj.bar(1,2,3))
+    foo $obj.bar(): 1,2,3   # special, means foo($obj.bar(1,2,3))
+    foo $obj.bar(1): 2,3    # special, means foo($obj.bar(1,2,3))
+    foo $obj.bar(1,2): 3    # special, means foo($obj.bar(1,2,3))
+    foo($obj.bar): 1,2,3    # special, means foo($obj.bar, 1,2,3)
+    foo($obj.bar, 1): 2,3   # special, means foo($obj.bar, 1,2,3)
+    foo($obj.bar, 1,2): 3   # special, means foo($obj.bar, 1,2,3)
+    foo $obj.bar : 1,2,3    # infix:<:>, means $obj.bar.foo(1,2,3)
+    foo ($obj.bar): 1,2,3   # infix:<:>, means $obj.bar.foo(1,2,3)
+    foo $obj.bar:1,2,3      # syntax error
+    foo $obj.bar :1,2,3     # syntax error
+    foo $obj.bar :baz       # adverb, means foo($obj.bar(:baz))
+    foo ($obj.bar) :baz     # adverb, means foo($obj.bar, :baz)
+    foo $obj.bar:baz        # extended identifier, foo( $obj.'bar:baz' )
+    foo $obj.infix:<+>      # extended identifier, foo( $obj.'infix:<+>' )
+    foo: 1,2,3              # label at statement start, else infix
+
+The moral of the story is, if you don't know how the colon is
+going to bind, use whitespace or parentheses to make it clear.
+
 =back
 
 =head2 List infix precedence
@@ -1827,18 +1880,6 @@
 
 =item *
 
-C<< infix:<:> >>, the invocant marker
-
-    say $*OUT: "howdy, world"
-
-The colon operator turns method calls and contextualizers into
-list operators.  It's not really a general operator; much like list
-assignment, it takes a special syntax on the left side and turns it
-into a list operator over the list on the right.  See L</Invocant
-marker>.
-
-=item *
-
 Normal listops
 
     print push say join split substr open etc.
@@ -2336,7 +2377,8 @@
 
 =item *
 
-The unary backslash operator captures its arguments, and returns an
+The unary backslash operator is not really an operator, but a special noun 
form.
+It "captures" its argument or arguments, and returns an
 object representing those arguments.  You can I<dereference> this object
 in several ways to retrieve different parts of the arguments; see the
 definition of C<Capture> in S02 for details.  (No whitespace is allowed

Modified: src/perl6/Cursor.pmc
===================================================================
--- src/perl6/Cursor.pmc        2009-01-26 01:45:30 UTC (rev 25030)
+++ src/perl6/Cursor.pmc        2009-01-26 04:06:43 UTC (rev 25031)
@@ -12,7 +12,7 @@
 require 'mangle.pl';
 
 our $CTX = '';
-our $DEBUG = defined($ENV{STD5DEBUG}) ? 1 : 0;
+our $DEBUG = 0 + ($ENV{STD5DEBUG} // 0);
 our $DEPTH = 0;
 our %LEXERS;       # per language, the cache of lexers, keyed by rule name
 our %FATECACHE; # fates we've already turned into linked lists

Modified: src/perl6/STD.pm
===================================================================
--- src/perl6/STD.pm    2009-01-26 01:45:30 UTC (rev 25030)
+++ src/perl6/STD.pm    2009-01-26 04:06:43 UTC (rev 25031)
@@ -14,6 +14,8 @@
 my $ORIG is context;
 my @MEMOS is context;
 my $VOID is context<rw>;
+my $INVOCANT_OK is context<rw>;
+my $INVOCANT_IS is context<rw>;
 my @PADS;
 
 # random rule for debugging, please ignore
@@ -1036,7 +1038,7 @@
     | <colonpair> {
             $<fake> = 1;
             $<sym> = ':';
-            %<O><prec> = %comma<prec>;
+            %<O><prec> = %comma<prec>;  # actual test is non-inclusive of 
comma!
             %<O><assoc> = 'unary';
             %<O><uassoc> = 'left';
         }
@@ -1055,7 +1057,7 @@
 
 # doing fancy as one rule simplifies LTM
 token dotty:sym<.*> ( --> Methodcall) {
-    ('.' [ <[+*?=:]> | '^' '!'? ]) :: <.unspacey> <dottyop>
+    ('.' [ <[+*?=]> | '^' '!'? ]) :: <.unspacey> <dottyop>
     { $<sym> = $0.item; }
 }
 
@@ -1071,6 +1073,7 @@
     :dba('dotty method or postfix')
     [
     | <methodop>
+    | <colonpair>
     | <!alpha> <postop> { $<O> = $<postop><O>; $<sym> = $<postop><sym>; }  # 
only non-alpha postfixes have dotty form
     ]
 }
@@ -1215,6 +1218,10 @@
     ]?
 }
 
+token semiarglist {
+    <arglist> ** ';'
+}
+
 token arglist {
     :my StrPos $endargs is context<rw> = 0;
     :my $GOAL is context = 'endargs';
@@ -1222,7 +1229,20 @@
     :dba('argument list')
     [
     | <?stdstopper>
-    | <EXPR(item %list_prefix)>
+    | <EXPR(item %list_prefix)> {{
+            my $delims = $<EXPR><delims>;
+            for @$delims {
+                if ($_.<sym> // '') eq ':' {
+                    if $+INVOCANT_OK {
+                        $+INVOCANT_IS = $<EXPR><list>[0];
+                    }
+                    else {
+                        $¢.panic("Illegal use of colon as invocant marker");
+                    }
+                }
+                $+INVOCANT_OK = 0;
+            }
+        }}
     ]
 }
 
@@ -2959,6 +2979,9 @@
 token infix:sym<%> ( --> Multiplicative)
     { <sym> }
 
+token infix:sym<mod> ( --> Multiplicative)
+    { <sym> }
+
 token infix:sym<+&> ( --> Multiplicative)
     { <sym> }
 
@@ -3086,31 +3109,7 @@
 token infix:sym<^..^> ( --> Nonchaining)
     { <sym> }
 
-token infix:sym<ff> ( --> Nonchaining)
-    { <sym> }
 
-token infix:sym<^ff> ( --> Nonchaining)
-    { <sym> }
-
-token infix:sym<ff^> ( --> Nonchaining)
-    { <sym> }
-
-token infix:sym<^ff^> ( --> Nonchaining)
-    { <sym> }
-
-token infix:sym<fff> ( --> Nonchaining)
-    { <sym> }
-
-token infix:sym<^fff> ( --> Nonchaining)
-    { <sym> }
-
-token infix:sym<fff^> ( --> Nonchaining)
-    { <sym> }
-
-token infix:sym<^fff^> ( --> Nonchaining)
-    { <sym> }
-
-
 ## chaining binary
 token infix:sym<==> ( --> Chaining)
     { <sym> }
@@ -3209,6 +3208,30 @@
 token infix:sym<?> ( --> Conditional)
     { <sym> <.obs('?: for the conditional operator', '??!!')> }
 
+token infix:sym<ff> ( --> Conditional)
+    { <sym> }
+
+token infix:sym<^ff> ( --> Conditional)
+    { <sym> }
+
+token infix:sym<ff^> ( --> Conditional)
+    { <sym> }
+
+token infix:sym<^ff^> ( --> Conditional)
+    { <sym> }
+
+token infix:sym<fff> ( --> Conditional)
+    { <sym> }
+
+token infix:sym<^fff> ( --> Conditional)
+    { <sym> }
+
+token infix:sym<fff^> ( --> Conditional)
+    { <sym> }
+
+token infix:sym<^fff^> ( --> Conditional)
+    { <sym> }
+
 ## assignment
 # There is no "--> type" because assignment may be coerced to either
 # item assignment or list assignment at "make" time.
@@ -3251,7 +3274,7 @@
     { <sym> }
 
 token infix:sym<:> ( --> Comma)
-    { <sym> }
+    { <sym> <?before \s | <terminator> > }
 
 token infix:sym« p5=> » ( --> Comma)
     { <sym> }
@@ -3295,7 +3318,7 @@
     { $t = $<identifier>.text; }
     <args( $¢.is_type($t) )>
     {{
-        %ROUTINES{$t} ~= $¢.lineof($¢.pos) ~ ' ' unless $¢.is_routine($t);
+        %ROUTINES{$t} ~= $¢.lineof($¢.pos) ~ ' ' unless $<args><invocant> or 
$¢.is_routine($t);
     }}
 }
 
@@ -3307,17 +3330,20 @@
 token args ($istype = 0) {
     :my $listopish = 0;
     :my $GOAL is context = '';
+    :my $INVOCANT_OK is context<rw> = 1;
+    :my $INVOCANT_IS is context<rw>;
     [
-    | :dba('argument list') '.(' ~ ')' <semilist> {*}             #= func args
-    | :dba('argument list') '(' ~ ')' <semilist> {*}              #= func args
-    | :dba('argument list') <.unsp> '.'? '(' ~ ')' <semilist> {*} #= func args
-    | {} [<?before \s> <!{ $istype }> <.ws> <!infixstopper> 
<listopargs=arglist> { $listopish = 1 }]?
+    | :dba('argument list') '.(' ~ ')' <semiarglist> {*}             #= func 
args
+    | :dba('argument list') '(' ~ ')' <semiarglist> {*}              #= func 
args
+    | :dba('argument list') <.unsp> '.'? '(' ~ ')' <semiarglist> {*} #= func 
args
+    |  { $listopish = 1 } [<?before \s> <!{ $istype }> <.ws> <!infixstopper> 
<arglist>]?
     ]
+    { $<invocant> = $INVOCANT_IS; }
 
     :dba('extra arglist after (...):')
     [
     || <?{ $listopish }>
-    || ':' <?before \s> <listopargs=arglist>    # either switch to listopiness
+    || ':' <?before \s> <moreargs=arglist>    # either switch to listopiness
     || {{ $<O> = {}; }}   # or allow adverbs (XXX needs hoisting?)
     ]
 }
@@ -3353,9 +3379,6 @@
 token infix:sym<andthen> ( --> Loose_and)
     { <sym> }
 
-token infix:sym<andthen> ( --> Loose_and)
-    { <sym> }
-
 ## loose or
 token infix:sym<or> ( --> Loose_or)
     { <sym> }
@@ -3366,9 +3389,7 @@
 token infix:sym<xor> ( --> Loose_or)
     { <sym> }
 
-token infix:sym<orelse> ( --> Loose_or)
-     { <sym> }
-
+## sequencer
 token infix:sym« <== » ( --> Sequencer)
     { <sym> }
 
@@ -3655,7 +3676,7 @@
                     when 'chain' { }            # just shift
                     when 'unary' { }            # just shift
                     when 'list'  {              # if op differs reduce else 
shift
-                        reduce() if $infix<sym> !eqv @opstack[*-1]<sym>;
+                       # reduce() if $infix<sym> !eqv @opstack[*-1]<sym>;
                     }
                     default { $here.panic('Unknown associativity "' ~ $_ ~ '" 
for "' ~ $infix<sym> ~ '"') }
                 }
@@ -3946,7 +3967,7 @@
             ]
     }
 
-    token assertion:identifier { <identifier> [               # is qq right 
here?
+    token assertion:identifier { <longname> [               # is qq right here?
                                     | <?before '>' >
                                     | <.ws> <nibbler>
                                     | '=' <assertion>
@@ -4193,7 +4214,7 @@
         [ <?before ')'> || <.panic: "Unable to parse Perl 5 regex; couldn't 
find right parenthesis"> ]
     }
 
-    #token assertion:identifier { <identifier> [               # is qq right 
here?
+    #token assertion:identifier { <longname> [               # is qq right 
here?
     #                                | <?before ')' >
     #                                | <.ws> <nibbler>
     #                               ]

Modified: t/spec/S02-names_and_variables/names.t
===================================================================
--- t/spec/S02-names_and_variables/names.t      2009-01-26 01:45:30 UTC (rev 
25030)
+++ t/spec/S02-names_and_variables/names.t      2009-01-26 04:06:43 UTC (rev 
25031)
@@ -22,7 +22,7 @@
 #?rakudo 3 skip "Parse error"
     is(Terrain::Hill::<$mountain>, 1024, 'varaible name with sigil not in 
front of 2 package levels deep');
     is($Terrain::($mountain)::mountain, 1024, 'variable name with a package 
name partially given by a variable ');
-    is($($river)::mountain, 1024, 'variable name with package name completely 
given by variable');
+    is($::($river)::mountain, 1024, 'variable name with package name 
completely given by variable');
 }
 
 {

Modified: t/spec/S29-hash/exists.t
===================================================================
--- t/spec/S29-hash/exists.t    2009-01-26 01:45:30 UTC (rev 25030)
+++ t/spec/S29-hash/exists.t    2009-01-26 04:06:43 UTC (rev 25031)
@@ -32,7 +32,7 @@
 
     my $b = %h1<b>;
     #?rakudo skip 'unspecced'
-    is (exists %h1, 'a'), 1, "Test existence for single key. (Indirect 
notation)";
+    is (exists %h1: 'a'), 1, "Test existence for single key. (Indirect 
notation)";
     is (%h1.exists('a')), 1, "Test existence for single key. (method call)";
 };
 

Reply via email to