Author: larry
Date: Wed Mar 14 11:08:52 2007
New Revision: 14346

Modified:
   doc/trunk/design/syn/S06.pod

Log:
Further refinement of caller semantics to dwim in displaced closure calls.


Modified: doc/trunk/design/syn/S06.pod
==============================================================================
--- doc/trunk/design/syn/S06.pod        (original)
+++ doc/trunk/design/syn/S06.pod        Wed Mar 14 11:08:52 2007
@@ -1735,6 +1735,11 @@
     $ctx = context(1,0,1,1); # my context's context's context's context
     $ctx = context($i);      # $i'th context
 
+Note also that negative numbers are allowed as long as you stay within
+the existing context stack:
+
+    $ctx = context(4,-1);    # my context's context's context's context
+
 Repeating any smartmatch just matches the same context again unless you
 intersperse a 1 to skip the current level:
 
@@ -1764,12 +1769,15 @@
     $ctx = context;
     $ctx = context.context.context.context;                # same
 
-The C<caller> function is special-cased to pay attention only to
-the current C<Routine> scope.  It is defined as navigating to the
-innermost scope matching C<&?ROUTINE> (which may be a no-op when
-immediately inside a routine) and then going out one context from that:
-
-    &caller ::= &context.assuming(&?ROUTINE,1);
+The C<caller> function is special-cased to go outward just far enough
+to escape from the current routine scope, after first ignoring any
+inner blocks that are embedded, or are otherwise pretending to be "inline":
+
+    &caller ::= &context.assuming({ !.inline }, 1);
+
+Note that this is usually the same as C<context(&?ROUTINE,1)>,
+but not always.  A call to a returned closure might not even have
+C<&?ROUTINE> in its dynamic scope anymore, but it still has a caller.
 
 So to find where the current routine was called you can say:
 
@@ -1781,10 +1789,12 @@
     say " file ", CALLER::<$?FILE>,
         " line ", CALLER::<$?LINE>;
 
-Note that one context out is I<not> guaranteed to be a C<Routine>
-context.  You must say C<caller(Routine)> to get to the next-most-inner
-routine, which is equivalent to C<context(&?ROUTINE,1,Routine)>.
-But C<caller(Routine).line> is not necessarily going to give you the
+Additional arguments to C<caller> are treated as navigational from the
+calling context.  One context out from your current routine is I<not>
+guaranteed to be a C<Routine> context.  You must say C<caller(Routine)>
+to get to the next-most-inner routine.
+
+Note that C<caller(Routine).line> is not necessarily going to give you the
 line number that your current routine was called from; you're rather
 likely to get the line number of the topmost block that is executing
 within that outer routine, where that block contains the call to
@@ -1793,18 +1803,27 @@
 For either C<context> or C<caller>,
 the returned context object supports at least the following methods:
 
-    .want
     .context
     .caller
+    .leave
+    .want
+    .inline
     .my
     .file
     .line
     .subname
 
-The C<.caller> method is subtly different from the C<caller>
-function.  Instead of looking up the current lexically scoped caller
-by C<.context(&?ROUTINE,1)>, it just looks up the next matching dynamic
-caller using C<.context(Routine,1)>.
+The C<.context> and C<.caller> methods work the same as the functions
+except that they are relative to the context supplied as invocant.
+The C<.leave> method can force an immediate return from the
+specified context.  The C<.want> method returns known smart-matchable
+characteristics of the specified context.
+
+The C<.inline> method says whether this block was entered implicitly
+by some surrounding control structure.  Any time you invoke a block or
+routine explicitly with C<.()> this is false.  However, it is defined
+to be true for any block entered using dispatcher-level primitives
+such as C<.callwith>, C<.callsame>, C<.nextwith>, or C<.nextsame>.
 
 The C<.my> method provides access to the lexical namespace in effect at
 the given dynamic context's current position.  It may be used to look

Reply via email to