Author: larry
Date: Thu Oct  9 16:40:10 2008
New Revision: 14591

Modified:
   doc/trunk/design/syn/S02.pod
   doc/trunk/design/syn/S03.pod
   doc/trunk/design/syn/S12.pod

Log:
Make operator adverbs parse sanely based on precedence.  They are now treated
as "loose unaries" (albeit still in a trailing position), and no longer require
the parser to track "previous operator".  The benefits are construed to
outweigh the problems.

Note also that existence and deletion are now simply adverbs on subscript
operators.


Modified: doc/trunk/design/syn/S02.pod
==============================================================================
--- doc/trunk/design/syn/S02.pod        (original)
+++ doc/trunk/design/syn/S02.pod        Thu Oct  9 16:40:10 2008
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 10 Aug 2004
-  Last Modified: 1 Sep 2008
+  Last Modified: 9 Oct 2008
   Number: 2
-  Version: 137
+  Version: 138
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -1531,19 +1531,42 @@
 
     @array = <A B>;
     @array[0,1,2];      # returns 'A', 'B', undef
-    @array[0,1,2]:p;    # returns 0 => 'A', 1 => 'B'
-    @array[0,1,2]:kv;   # returns 0, 'A', 1, 'B'
-    @array[0,1,2]:k;    # returns 0, 1
-    @array[0,1,2]:v;    # returns 'A', 'B'
+    @array[0,1,2] :p;   # returns 0 => 'A', 1 => 'B'
+    @array[0,1,2] :kv;  # returns 0, 'A', 1, 'B'
+    @array[0,1,2] :k;   # returns 0, 1
+    @array[0,1,2] :v;   # returns 'A', 'B'
 
     %hash = (:a<A>, :b<B>);
     %hash<a b c>;       # returns 'A', 'B', undef
-    %hash<a b c>:p;     # returns a => 'A', b => 'B'
-    %hash<a b c>:kv;    # returns 'a', 'A', 'b', 'B'
-    %hash<a b c>:k;     # returns 'a', 'b'
-    %hash<a b c>:v;     # returns 'A', 'B'
-
-The adverbial forms all weed out non-existing entries.
+    %hash<a b c> :p;    # returns a => 'A', b => 'B'
+    %hash<a b c> :kv;   # returns 'a', 'A', 'b', 'B'
+    %hash<a b c> :k;    # returns 'a', 'b'
+    %hash<a b c> :v;    # returns 'A', 'B'
+
+These adverbial forms all weed out non-existing entries.  You may also
+perform an existence test, which will return true if all the elements
+of the slice exist:
+
+    if %hash<a b c> :exists {...}
+
+likewise,
+
+    my ($a,$b,$c) = %hash<a b c> :delete;
+
+deletes the entries "en passant" while returning them.  (Of course,
+any of these forms also work in the degenerate case of a slice
+containing a single index.)  Note that these forms work by virtue
+of the fact that the subscript is the topmost previous operator.
+You may have to parenthesize or force list context if some other
+operator that is tighter than comma would appear to be topmost:
+
+    1 + (%hash{$x} :delete);
+    $x = (%hash{$x} :delete);
+    ($x) = %hash{$x} :delete;
+
+(The situation does not often arise for the slice modifiers above
+because they are usually used in list context, which operators
+at comma precedence.)
 
 =item *
 
@@ -2316,11 +2339,12 @@
 identifier keys) are considered special tokens and are recognized
 in various positions in addition to term position.  In particular,
 when used where an infix would be expected they modify the previous
-operator, ignoring the intervening term or parenthesized argument:
+topmost operator that is tighter in precedence than "loose unary"
+(see S03):
 
     1 .. 100 :by(3)     # count to 100 by threes
 
-Within declarations the form is used to rename parameter declarations:
+Within declarations the adverbial form is used to rename parameter 
declarations:
 
     sub foo ( :externalname($myname) ) {...}
 
@@ -2377,9 +2401,15 @@
 See S06 for the use of adverbs as named arguments.
 
 The negated form (C<:!a>) and the sigiled forms (C<:$a>, C<:@a>,
-C<:%a>) never take an argument and don't care what the next character is.
-They are considered complete.  These forms require an identifier to
-serve as the key.
+C<:%a>) never take an argument and don't care what the next character
+is.  They are considered complete.  These forms require an identifier
+to serve as the key.
+
+For identifiers that take a numeric argument, it is allowed to
+abbreviate, for example, C<:sweet(16)> to C<:16sweet>.  (This is
+distinguishable from the :16<deadbeef> form, which never has an
+alphabetic character following the number.)  Only literal decimal
+numbers may be swapped this way.
 
 The other forms of adverb (including the bare C<:a> form) I<always>
 look for an immediate bracketed argument, and will slurp it up.

Modified: doc/trunk/design/syn/S03.pod
==============================================================================
--- doc/trunk/design/syn/S03.pod        (original)
+++ doc/trunk/design/syn/S03.pod        Thu Oct  9 16:40:10 2008
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 8 Mar 2004
-  Last Modified: 8 Oct 2008
+  Last Modified: 9 Oct 2008
   Number: 3
-  Version: 142
+  Version: 143
 
 =head1 Overview
 
@@ -47,7 +47,7 @@
     X  Tight or          || ^^ // min max
     L  Conditional       ?? !! ff fff
     R  Item assignment   = := ::= => += -= **= xx= .=
-    L  Loose unary       true not
+    L  Loose unary       true not :by(2)
     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 $ @
@@ -1455,6 +1455,60 @@
 
 =back
 
+While the preceding are parsed as prefix operators, operator adverbs
+are parsed as trailing unary operators at this precedence level,
+just tighter than comma.  (They're not officially "postfix" operators
+because those require the absense of whitespace, and these allow whitespace.
+These adverbs insert themselves in the spot where the parser is
+expecting an infix operator, but the parser continues to look for
+an infix after parsing the adverb and applying it to the previous
+term.)  Thus,
+
+    $a < 1 and $b == 2 :carefully
+
+does the C<==> carefully, while
+
+    $a < 1 && $b == 2 :carefully
+
+does the C<&&> carefully because C<&&> is of
+tighter precedence than "loose unary".  Use
+
+    $a < 1 && ($b == 2 :carefully)
+
+to apply the adverb to the C<==> operator instead.  We say that
+C<==> is the "topmost" operator in the sense that it is at the
+top of the parse tree that the adverb could possibly apply to.
+(It could not apply outside the parens.)  If you are unsure
+what the topmost operator is, just ask yourself which operator
+would be applied last.  For instance, in
+
+    +%hash{$key} :foo
+
+The subscript happens first and the C<+> operator happens last,
+so C<:foo> would apply to that.  Use
+
+    +(%hash{$key} :foo)
+
+to apply C<:foo> to the subscripting operator instead.  Likewise
+
+    $x = 1..10:by(2)
+
+will apply the adverb to the item assignment (and fail), but since
+
+    @x = 1..10:by(2)
+
+is a (looser) list assignment, the adverb applies to the range operator
+as expected.  And in general note that adverbs will attach the way
+you want when you say things like
+
+    1 .. $x+2 :by(2)
+
+The new internal testing syntax makes use of these precedence rules:
+
+    $x eqv $y+2  :ok<$x is equivalent to $y+2>;
+
+Here the adverb is considered to be modifying the C<eqv> operator.
+
 =head2 Comma operator precedence
 
 =over
@@ -2449,8 +2503,8 @@
 syntactic category of the next item.  Parentheses (with or without
 a dot) turn the list operator into a function call instead, and
 all the function's arguments must be passed inside the parentheses
-(with the sole exception of an adverbial block, which may follow the
-parentheses).
+(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
 disallowed immediately after a list operator, even if there are no
@@ -3232,7 +3286,7 @@
 
     $hacker.feed:xxx('Pizza and cola');
 
-is tokenized as an adverb applying to the method as its "preceding operator":
+is tokenized as an adverb applying to the method as its "toplevel preceding 
operator":
 
     $hacker.feed :xxx('Pizza and cola');
 
@@ -3247,6 +3301,13 @@
 
 (For similar reasons it's required to put whitespace after the colon of a 
label.)
 
+Note in particular that because of adverbial precedence:
+
+    1 + $hacker.feed :xxx('Pizza and cola');
+
+will apply the C<:xxx> adverb to the C<+> operator, not the method call.
+This is not likely to succeed.
+
 =head1 Feed operators
 
 The new operators C<< ==> >> and C<< <== >> are akin to UNIX pipes,

Modified: doc/trunk/design/syn/S12.pod
==============================================================================
--- doc/trunk/design/syn/S12.pod        (original)
+++ doc/trunk/design/syn/S12.pod        Thu Oct  9 16:40:10 2008
@@ -745,26 +745,6 @@
 properties.  (Also note that syntactic category names are reserved for
 calling operators as if they were methods.)
 
-Depending on the class, the pairs in question may have arguments.
-The C<Hash> class in particular makes use of pair syntax for subscript
-modifiers:
-
-    %hash.:exists{$key}
-    %hash.:delete{$key}
-
-This has the advantage that the pair's argument is actually parsed exactly
-as a subscript would be.  A C<.exists()> method could not easily make
-such a guarantee about its arguments.  Plus you can say:
-
-    %hash.:exists<foo>
-    %hash.:delete<foo>
-
-Conjecture, the trailing subscript adverbs could be brought up front as
-well:
-
-    @array.:[EMAIL PROTECTED]
-    %hash.:[EMAIL PROTECTED]
-
 =head1 Calling sets of methods
 
 For any method name, there may be some number of candidate methods

Reply via email to