Project

General

Profile

Bug #10636

4GL FOR FIRST LEAVE statement exits the function

Added by Teodor Gorghe 10 months ago. Updated 6 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Target version:
-
Start date:
Due date:
% Done:

100%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:
production:
No
env_name:
topics:

History

#1 Updated by Teodor Gorghe 10 months ago

On OE 11.6, there is a strange feature, when there is a LEAVE statement on a FOR block with a RECID or ROWID in where clause, in an OO method, 4GL does not leave the current FOR block but acts like RETURN ?.

On FWD, the LEAVE statement leaves the FOR block, in all cases, and then executes what is next in the current method.

#3 Updated by Teodor Gorghe 10 months ago

On OE 11.6, this does not happen when the RECID/ROWID function is used on an inequality condition.
When there is more than 1 nested FOR loop, all with the RECID/ROWID equality condition, the method exit happens. If one nested FOR block does not have that equality, then the LEAVE statement acts like it should be, leaving the current block.

#4 Updated by Greg Shah 10 months ago

There are other cases when the 4GL decides to convert a LEAVE (or a NEXT) to a RETURN.

You can look inside rules/annotations/block_properties.rules and you will find sections like this:

      <!-- ON phrases and the UNDO statement can be specified with secondary
           actions (RETRY, LEAVE, NEXT) which have no explicit target (label),
           in such cases the target is always the same as the target of the
           UNDO AND depending on the target block properties, the action may
           be statically converted as in the following:

           1. If the action is LEAVE or NEXT and the target block is a
              top-level block, then the action will be converted to a RETURN.
           2. If the action is NEXT and the target block is a non-iterating
              inner block (it is not a top-level block), then the NEXT will
              be converted to a LEAVE.

           RETURN is an action that never references a label so it is
           ignored in this processing.

           RETRY will automatically be targetted to the same block as a
           pending UNDO by the runtime, so it can be ignored here. This means
           that we avoid emitting an extra string in the converted source
           code, which is better.
           -->
...
      <!-- NEXT statement that explicitly targets a FOR FIRST/LAST must
           convert to a LEAVE -->
...
      <!-- NEXT statement without an explicit target (label) must have one
           calculated in this 3 phase process:

           1. The nearest enclosing iterating block.
           2. The nearest enclosing FOR FIRST/LAST.  In this case, the NEXT
              will be statically converted to a LEAVE.
           3. NEXT converts to a RETURN (because it is implicitly targetting
              a top-level block).

           Note that a more deeply nested FOR FIRST/LAST will NOT take
           precedence over a more enclosing looping block. So each phase of
           this search must be executed completely before the next phase can
           start.

           -->
...
      <!-- LEAVE statement without an explicit target (label) must have one
           calculated:

           1. The nearest enclosing non-simple DO inner block.
           2. LEAVE converts to RETURN (because it is implicitly targetting
              a top-level block).

           -->

Please consider those conditions and try to determine how labeling, NEXT etc... work in your cases.

#5 Updated by Constantin Asofiei 10 months ago

Teodor, I think this is just the target of the leave/next is the outer block in such case:

def var r as rowid.

find first book.
r = rowid(book).
release book.

def var l as log.

repeat:
   message "next" l.
   if l then leave.
   l = true.
   for first book where rowid(book) = r:
      message "here".
      if l then next.  // looks like this targets the outer block by default if 'rowid' (or 'recid'?) is used
   end.

   message "done".
end.

message "finished".

This shows 'finished' and executes the REPEAT twice.

Is not just that it converts to RETURN.

Please test with something other than OE11.6 also.

#6 Updated by Constantin Asofiei 10 months ago

Also, you can target the FOR block in OE if it has an explicit label and that is used for leave/next. So just the implicit label seems to be impacted.

#7 Updated by Teodor Gorghe 9 months ago

  • Assignee set to Teodor Gorghe
  • Status changed from New to WIP

Created task branch 10636a.

#8 Updated by Teodor Gorghe 9 months ago

  • Status changed from WIP to Review
  • % Done changed from 0 to 100
  • reviewer Constantin Asofiei added

Committed revision 16215 on task branch 10636a:
- NEXT/LEAVE points to the outer block, when the current FOR BLOCK has RECID/ROWID equality on WHERE clause.

#9 Updated by Constantin Asofiei 6 months ago

  • Status changed from Review to Internal Test

#10 Updated by Teodor Gorghe 6 months ago

Rebased task branch 10636a to trunk revision 16358.

#11 Updated by Constantin Asofiei 6 months ago

  • Status changed from Internal Test to Merge Pending

Merge to trunk after 10560a

#12 Updated by Teodor Gorghe 6 months ago

  • Status changed from Merge Pending to Test

Branch 10636a was merged to trunk rev. 16385 and archived.

#13 Updated by Constantin Asofiei 6 months ago

  • Status changed from Test to Closed

Also available in: Atom PDF