Project

General

Profile

Feature #2016

implement CURRENT-WINDOW, ACTIVE-WINDOW and DEFAULT-WINDOW system handles

Added by Greg Shah about 11 years ago. Updated over 7 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Start date:
02/20/2013
Due date:
08/13/2013
% Done:

100%

Estimated time:
(Total: 40.00 h)
billable:
No
vendor_id:
GCD

cs_upd20130222c.zip (60 KB) Costin Savin, 02/22/2013 02:49 PM

ca_upd20130223a.zip (115 KB) Constantin Asofiei, 02/23/2013 02:30 AM

window_handle.p Magnifier (1.94 KB) Constantin Asofiei, 02/23/2013 02:30 AM

ca_upd20130223g.zip (54.9 KB) Constantin Asofiei, 02/23/2013 12:29 PM

ca_upd20130224b.zip (139 KB) Constantin Asofiei, 02/24/2013 08:54 AM

window_handle.p Magnifier (2.7 KB) Constantin Asofiei, 02/24/2013 08:54 AM

vig_upd20131226a.zip (50.6 KB) Vadim Gindin, 12/25/2013 06:55 PM

vig_upd20140107a.zip (88.5 KB) Vadim Gindin, 01/07/2014 12:56 PM

vig_upd20140107a.zip (88.5 KB) Vadim Gindin, 01/07/2014 01:01 PM

vig_upd20140108a.zip (108 KB) Vadim Gindin, 01/08/2014 07:01 PM

vig_upd20140109b.zip (110 KB) Vadim Gindin, 01/09/2014 05:14 PM

vig_upd20140115a.zip (111 KB) Vadim Gindin, 01/15/2014 05:47 PM

vig_upd20140116a.zip (115 KB) Vadim Gindin, 01/16/2014 06:59 PM


Subtasks

Feature #2017: conversion sypport for CURRENT-WINDOW, ACTIVE-WINDOW and DEFAULT-WINDOW system handlesClosedCostin Savin

Feature #2018: runtime support for CURRENT-WINDOW, ACTIVE-WINDOW and DEFAULT-WINDOW system handlesClosedVadim Gindin


Related issues

Related to User Interface - Feature #2229: implement CURRENT-WINDOW, ACTIVE-WINDOW and DEFAULT-WINDOW system handles for GUI Closed
Related to User Interface - Feature #2252: implement GUI client support Closed 03/24/2014

History

#1 Updated by Greg Shah about 11 years ago

CURRENT-WINDOW is assignable but neither DEFAULT-WINDOW or ACTIVE-WINDOW can be assigned.

DEFAULT-WINDOW is a handle to the unnamed window that exists at the start of every GUI session AND which is the only window that exists in a CHUI environment.

CURRENT-WINDOW is a handle to the window that will be the default parent for any frames/dialogs created in the current procedure (unless the code uses an explicit IN WINDOW phrase). It can be modified for the scope of a given procedure using the proc_handle:CURRENT-WINDOW. It can be assigned, to allow application control over the default parent. Initially (until tha app assigns to it) this will be equivalent to the DEFAULT-WINDOW.

ACTIVE-WINDOW is a handle to the window that most recently received an ENTRY event.

All 3 handles can be used to read/write attributes and methods. All 3 handles are full fledged window widgets. These are just well-known named handles that can be used to reference the associated window.

Common use cases:

CURRENT-WINDOW = some-window-handle.
CURRENT-WINDOW = ACTIVE-WINDOW.
THIS-PROCEDURE:CURRENT-WINDOW = some-window-handle.  /* this one is not the CURRENT-WINDOW handle, but is highly related */
my-handle-var = CURRENT-WINDOW.
my-handle-var = DEFAULT-WINDOW.
my-handle-var = ACTIVE-WINDOW.
RUN some-proc (INPUT CURRENT-WINDOW, ...).
my-num-var = CURRENT-WINDOW:HWND.
CURRENT-WINDOW:SENSITIVE = true.
WAIT-FOR CLOSE of CURRENT-WINDOW.
ON WINDOW-CLOSE OF CURRENT-WINDOW DO:

These handles should be maintained in the context-local portion of LogicalTerminal. This will need to integrate down to the client, so that changes are bidirectionally reflected. For example, the ENTRY event needs to maintain the ACTIVE-WINDOW on the client AND when control transfers back to the server, this must be reflected there too. Likewise, when CURRENT-WINDOW is assigned on the server it must be pushed down to the client the next time control transfers there.

We may have some fledgling support today, but it needs to be expanded to be complete.

#2 Updated by Costin Savin about 11 years ago

What will be the approach for system handles besides CURRENT-WINDOW that are assigned as left value.
It seems that for DEFAULT-WINDOW and ACTIVE-WINDOW (and also SESSION) an instruction which assigns a variable handle to them is valid though it does not change their value as opposed to CURRENT-WINDOW:

DEFINE VARIABLE win AS HANDLE NO-UNDO.
DEFINE SUB-MENU myfile
MENU-ITEM m1 LABEL "Save" 
MENU-ITEM m2 LABEL "Save as" 
MENU-ITEM m3 LABEL "Exit".
DEFINE MENU mybar MENUBAR
SUB-MENU myfile LABEL "File".

CREATE WINDOW win
    ASSIGN MENUBAR = MENU mybar:HANDLE.

DEFAULT-WINDOW = win.
ACTIVE-WINDOW = win.

IF DEFAULT-WINDOW = win THEN
    MESSAGE "Default changed to win".
IF DEFAULT-WINDOW = win THEN
    MESSAGE "Active Window changed to win".
CURRENT-WINDOW = win.

IF CURRENT-WINDOW = win THEN
    MESSAGE "Current-window changed".

What we do in the case of the system handles which shouldn't be setable? Throw an error at conversion, emit a set method and do nothing or emit a readOnlySystemHandle() method which throws an error?

#3 Updated by Costin Savin about 11 years ago

Added intermediate update merged to latest revision, this should cover the cases showed here minus the case for which we try to assign to a readable system-handle.

#4 Updated by Greg Shah about 11 years ago

Is the assignment of DEFAULT-WINDOW and ACTIVE-WINDOW (and SESSION) silently tolerated (and ignored) at runtime in the 4GL? Or is your comment regarding valid code only?

Throw an error at conversion, emit a set method and do nothing or emit a readOnlySystemHandle() method which throws an error?

We should do exactly what the 4GL does. If it generates an error at runtime, then we generate the same error. If it silently ignores the assignment, then we would provide a similar assignment that does nothing. Normally, we would prefer to just drop the code from the converted application. But it is possible that in the 4GL, the expression on the right side of the assignment operator (the rvalue) could have side-effects that must be maintained.

#5 Updated by Constantin Asofiei about 11 years ago

Is the assignment of DEFAULT-WINDOW and ACTIVE-WINDOW (and SESSION) silently tolerated (and ignored) at runtime in the 4GL?

Correct, 4GL silently ignores assignments of the SESSION, FILE-INFO, ERROR-STATUS, LAST-EVENT, SOURCE-PROCEDURE, TARGET-PROCEDURE, ACTIVE-WINDOW and DEFAULT-WINDOW. If THIS-PROCEDURE is used, then it gets compile-time error. The solution is:
  • for system handles SESSION, FILE-INFO, ERROR-STATUS, LAST-EVENT: as their asHandle implementation always returns a new handle instance, calling i.e. SessionUtils.asHandle().assign(h) will have no effect.
  • for TARGET- and SOURCE-PROCEDURE: the ProcedureManager.target/sourceProcedure APIs always return a new handle instance, so no problem here either.
  • for DEFAULT-WINDOW and ACTIVE-WINDOW: LogicalTerminal.setDefaultWindow and LogicalTerminal.setActiveWindow are emitted, which silently ignore the assignment.

With these changes, I don't think WindowWidget.assign can be called (and I don't think it should be called at all), so I removed it. Also, I left LogicalTerminal.sessionWindow intact (as now it is returned by both currentWindow and activeWindow), as I don't want to break anything.

#6 Updated by Constantin Asofiei about 11 years ago

Conversion regression testing passed on my system (no changes in generated code).

#7 Updated by Greg Shah about 11 years ago

I assume this update is merged up to bzr 10190? It is ready for testing?

#8 Updated by Constantin Asofiei about 11 years ago

Yes, is merged and ready for testing.

#9 Updated by Greg Shah about 11 years ago

The code looks good. It is in conversion testing now.

#10 Updated by Greg Shah about 11 years ago

Conversion testing has passed. Please check it in to bzr and distribute via email.

#11 Updated by Constantin Asofiei about 11 years ago

Committed to bzr revision 10191.

#12 Updated by Constantin Asofiei about 11 years ago

There is a problem when CURRENT/DEFAULT/ACTIVE-WINDOW are not used in an assignment, as in:

function func0 returns handle.
   return current-window.
end.

This should convert to something like LogicalTerminal.currentWindowHandle

#13 Updated by Greg Shah about 11 years ago

OK, please do fix it.

#14 Updated by Constantin Asofiei about 11 years ago

Fixed the issues at comment 12.

#15 Updated by Greg Shah about 11 years ago

The change looks fine. This is being conversion tested now.

#16 Updated by Greg Shah about 11 years ago

There are major changes in Majic. And those changes don't compile. This is an example change:

diff -r generated/20130223c/src/aero/timco/majic/util/VchviewVchHdr.java generated/20130223d/src/aero/timco/majic/util/VchviewVchHdr.java
136c136
<                   list4.addEvent("window-close", currentWindow());
---
>                   list4.addEvent("window-close", LogicalTerminal.currentWindowHandle());
223c223
<          currentWindow().apply("window-close");
---
>          LogicalTerminal.currentWindowHandle().apply("window-close");
232c232
<          currentWindow().apply("window-close");
---
>          LogicalTerminal.currentWindowHandle().apply("window-close");

Here are some representative compile errors (different file but same idea):

   [javac] /home/ges/timco/src/aero/timco/majic/so/Jmatloff.java:208: error: no suitable method found for addEvent(String[],handle)
    [javac]             list7.addEvent(new String[]
    [javac]                  ^
    [javac]     method EventList.addEvent(String,boolean) is not applicable
    [javac]       (actual argument String[] cannot be converted to String by method invocation conversion)
    [javac]     method EventList.addEvent(String) is not applicable
    [javac]       (actual and formal argument lists differ in length)
    [javac]     method EventList.addEvent(String[],boolean) is not applicable
    [javac]       (actual argument handle cannot be converted to boolean by method invocation conversion)
    [javac]     method EventList.addEvent(String[]) is not applicable
    [javac]       (actual and formal argument lists differ in length)
    [javac]     method EventList.addEvent(String[],CommonFrame) is not applicable
    [javac]       (actual argument handle cannot be converted to CommonFrame by method invocation conversion)
    [javac]     method EventList.addEvent(String,CommonFrame) is not applicable
    [javac]       (actual argument String[] cannot be converted to String by method invocation conversion)
    [javac]     method EventList.addEvent(String,handle) is not applicable
    [javac]       (actual argument String[] cannot be converted to String by method invocation conversion)
    [javac]     method EventList.addEvent(String,GenericWidget,boolean) is not applicable
    [javac]       (actual and formal argument lists differ in length)
    [javac]     method EventList.addEvent(String,GenericWidget[],boolean) is not applicable
    [javac]       (actual and formal argument lists differ in length)
    [javac]     method EventList.addEvent(String[],GenericWidget,boolean) is not applicable
    [javac]       (actual and formal argument lists differ in length)
    [javac]     method EventList.addEvent(String,GenericWidget) is not applicable
    [javac]       (actual argument String[] cannot be converted to String by method invocation conversion)
    [javac]     method EventList.addEvent(String[],GenericWidget) is not applicable
    [javac]       (actual argument handle cannot be converted to GenericWidget by method invocation conversion)
    [javac]     method EventList.addEvent(String,GenericWidget[]) is not applicable
    [javac]       (actual argument String[] cannot be converted to String by method invocation conversion)
    [javac]     method EventList.addEvent(String[],GenericWidget[]) is not applicable
    [javac]       (actual argument handle cannot be converted to GenericWidget[] by method invocation conversion)
    [javac]     method EventList.addEvent(String[],GenericWidget[],boolean) is not applicable
    [javac]       (actual and formal argument lists differ in length)
    [javac] /home/ges/timco/src/aero/timco/majic/so/Jmatloff.java:600: error: cannot find symbol
    [javac]          LogicalTerminal.currentWindowHandle().apply("window-close");
    [javac]                                               ^
    [javac]   symbol:   method apply(String)
    [javac]   location: class handle
    [javac] /home/ges/timco/src/aero/timco/majic/so/Serv21.java:3775: error: cannot find symbol
    [javac]             LogicalTerminal.currentWindowHandle().apply("window-close");

#17 Updated by Constantin Asofiei about 11 years ago

I was thinking for the implementation of the window system-handles to allow them to convert to an API which returns the actual widget, to avoid the handle unwrapping when events/attributes are accessed... but I don't think we can get away with this, as these handles (beside RETURN) can be set for a handle parameter in a func/proc call. I think it will be too time consuming to determine all cases when the window system handles need to act as a real handle and when it can act as a widget, so the solution will be to convert them as real handles, the way SELF was converted too.

#18 Updated by Constantin Asofiei about 11 years ago

Attached update makes the window system handles to convert as true handles; also, I've removed the THIS-PROCEDURE hack which converted it to currentWindow, if was used with WAIT-FOR, ON or APPLY.

Conversion regression testing has passed on my machine.

#19 Updated by Greg Shah about 11 years ago

Checked in as bzr revision 10196.

#20 Updated by Constantin Asofiei over 10 years ago

Check #1791 note 30 and forward for a discussion for findings about the current-/default-/active-window behaviour in batch and chui modes. Also, looks like width (and maybe other) attributes can not be changed in chui mode.

#21 Updated by Constantin Asofiei over 10 years ago

What needs to be done in CHUI/batch mode, for M7 (part of #2018):
- the window system handles all point to the same resource (#1791 - note 40). This might mean that in CHUI mode only one WINDOW resource exists, for a client session.
- check what happens when the window system handle is the left-side operand in an assignment (and it tries to assign it to a handle, system handle or to unknown). This should be either no-op, error message or validation of the right-side operand (followed by possible assignment).

There should be no need to touch UI-related code on P2J client side.

#22 Updated by Vadim Gindin over 10 years ago

Here are test cases:
1) same.p - testing equality of all three handles.

if current-window <> default-window then
  message "current do not equal to default".

if current-window <> active-window then
  message "current do not equal to active".

if default-window <> active-window then
  message "default do not equal to active".

Works for chui and batch modes.

2) width.p - try to assign an attribute of window system handles.

def var w as int.
w = current-window:width. 
current-window:width=101.
if current-window:width <> w then 
  message "current width was changed".

w = active-window:width.
active-window:width=101.
if active-window:width <> w then 
  message "active width was changed".

w = default-window:width.
default-window:width=101.
if default-window:width <> w then 
  message "default width was changed".

message "end.".

CHUI. Shows an error "** Unable to set attribute WIDTH on WINDOW widget in the current environment. (4079)"
3 times and "end." string at the end of output.
BATCH. Shows one error "Cannot access the WIDTH attribute because the widget does not exist. (3140)" once.
It seems that in batch mode these handles do no point on window.

3) width-noerror.p - try to use handles with NO-ERROR key

output to winhandles.

def var w as int.

w = current-window:width no-error. 
message error-status:error error-status:num-messages error-status:get-message(1).
w = active-window:width no-error.
message error-status:error error-status:num-messages error-status:get-message(1).
w = default-window:width no-error.
message error-status:error error-status:num-messages error-status:get-message(1).

message "end.".

CHUI. No errors. works
BATCH. error 3140 3 times and "end."

#23 Updated by Constantin Asofiei over 10 years ago

Vadim Gindin wrote:

Here are test cases:
1) same.p - testing equality of all three handles.
[...]

Works for chui and batch modes.

OK, this proves there is only one window in CHUI mode. Please test in batch mode if the window is unknown or not.

2) width.p - try to assign an attribute of window system handles.
3) width-noerror.p - try to use handles with NO-ERROR key

This findings are OK, but they can be implemented later. What I meant was to test cases like current-window = some-handle. - what happens with the system handle?

#24 Updated by Vadim Gindin over 10 years ago

Constantin Asofiei wrote:

Vadim Gindin wrote:

Here are test cases:
1) same.p - testing equality of all three handles.
[...]

Works for chui and batch modes.

OK, this proves there is only one window in CHUI mode. Please test in batch mode if the window is unknown or not.

window is unknown:
message current-window active-window default-window outputs ? ? ?

2) width.p - try to assign an attribute of window system handles.
3) width-noerror.p - try to use handles with NO-ERROR key

This findings are OK, but they can be implemented later. What I meant was to test cases like current-window = some-handle. - what happens with the system handle?

I added couple of simple tests and found that current-window behaves little different that other handles.

def var wh as widget-handle.
output to 3333.

wh = ?.

message "aw before: " active-window.
active-window = wh.
message "aw after: " active-window.

message "dw before: " default-window.
default-window = wh.
message "dw after: " default-window.

In the result default-window and active-window remains unchanged. But the analogue procedure for the current-window shows and error.

def var wh as widget-handle.
output to 3333.

message "cw before: " current-window." 
current-window = wh.
message "cw after: " current-window.

Shows an error "Unable to evaluate field for assignment. (143)".

If we will assign some value to wh for example create button wh Progress will show the other error:
"Unable to assign widget to CURRENT-WINDOW. (3130)"

In batch mode this behavior doesn't changing.

If we assign to wh the active-window for example - all will work.

Finally I can't assign other valid window handle because it is not possible to create window in CHUI mode.

#25 Updated by Vadim Gindin over 10 years ago

no-error in the case of current-window errors sets ERROR-STATUS:ERROR flag to true.

#26 Updated by Vadim Gindin over 10 years ago

Here is an update. Sorry that it is merged with 1782 changes. It's not final. In this task there is only setCurrentWindow method implementations.

I found 2 problems:
1) current-window = h no-error - no-error is losed after conversion in this statement.
2) current-window = ? is converted to setCurrentWindow(new unkown()). Should I add additional setCurrentWindow method for this case or I should modify converstion rules to wrap ? to handle variable or widget variable?

#27 Updated by Constantin Asofiei over 10 years ago

Some general notes:
  1. in the implementations for all current/default/active-window APIs in LogicalTerminal, where it says do nothing I would prefer to be like this:
      if (isChui()) 
      {
          // in chui or batch mode, this is a no-op.
          return.
      }
    

    Please double check if we need to explicitly check for batch mode. This way, it's obvious we will need to do something different in GUI mode.
  2. please check and implement the CURRENT-WINDOW attribute for procedure widgets too. I suspect the behaviour will be the same.

Shows an error "Unable to evaluate field for assignment. (143)".

I think the correct error message is ** x.p: Unable to evaluate field for assignment. (143) where x.p is the program name. More, the Unable to assign widget to CURRENT-WINDOW. (3130) has two spaces between the widget and to words. Please make sure the error messages are emitted the same way as 4GL. The various boolean parameters for ErrorManager APIs are very helpful.

1) current-window = h no-error - no-error is losed after conversion in this statement.

Please fix it.

2) current-window = ? is converted to setCurrentWindow(new unkown()). Should I add additional setCurrentWindow method for this case or I should modify converstion rules to wrap ? to handle variable or widget variable?

The correct solution is to emit a new handle() instead of new unknown(). If the conversion changes look simple, go ahead and fix it (low priority).

#28 Updated by Vadim Gindin over 10 years ago

I'm trying to fix no-error loose during conversion of this statement:

current-window = h no-error.

I am viewing the grammar rule "assignment" (line 11992) in progress.g and It is a bit complex. Could you explain me what does the following statement mean:

  1. = #([ASSIGNMENT, "assignment"], (eq, l, e), rv, k); //line 12114

and where variables "eq", "l", "e", "rv" and "k" are defined?

This statement was parsed to this ast node:

   <ast col="16" id="1120986464286" line="8" text="=" type="EXPRESSION">
      <annotation datatype="java.lang.Boolean" key="wasassign" value="true"/>
      <annotation datatype="java.lang.Long" key="peerid" value="1159641169959"/>
      <ast col="1" id="1120986464289" line="8" text="current-window" type="SYS_HANDLE">
        <annotation datatype="java.lang.Long" key="oldtype" value="507"/>
        <annotation datatype="java.lang.Long" key="tempidx" value="197"/>
        <annotation datatype="java.lang.Long" key="peerid" value="1159641169960"/>
        <ast col="0" id="1120986464292" line="0" text="expression" type="EXPRESSION">
          <annotation datatype="java.lang.Long" key="peerid" value="1159641169961"/>
          <ast col="18" id="1120986464293" line="8" text="wh" type="VAR_HANDLE">
            <annotation datatype="java.lang.Long" key="oldtype" value="2348"/>
            <annotation datatype="java.lang.Long" key="refid" value="1120986464259"/>
            <annotation datatype="java.lang.Long" key="peerid" value="1159641169962"/>
          </ast>
        </ast>
      </ast>
    </ast>

And this node does not contain "no-error". Probably the case is in the progress.g

#29 Updated by Greg Shah over 10 years ago

First, in regard to your specific problem, I doubt the issue is in the parser. The NO-ERROR should emit as:

ErrorManager.silentErrorEnable();
// converted statement or expression
ErrorManager.silentErrorDisable();

This brackets the converted code with code that controls the "silent error" flag which is our equivalent to NO-ERROR.

Please see rules/convert/language_statements.rules and search for all instances of prog.kw_no_error to see the code.

To see if the problem is in the parser, look in the <sourcefile>.p.ast and search for line="<linenum>" then examine the tree there. If the KW_NO_ERROR node exists in the tree then the problem is somewhere else.

Please show the node above the EXPRESSION node in the tree. Is that an ASSIGNMENT? Are you looking at the AST before or after the TRPL rules may have changed it?

About the progress.g grammar:

and where variables "eq", "l", "e", "rv" and "k" are defined?

Look above there to see the definitions. For example, on line 12068 there is this code:

(k:KW_NO_ERROR)?

The k: is a label that defines a local AST variable named k. In actions (the Java code in {} inserted inline with the rest of the grammar), this is named #k. But for regular grammar references, just k will work. The other variables are defined as labels for the other parts of the matched text. These can be single tokens or they can be the root node of a sub-tree.

Could you explain me what does the following statement mean:

  1. = #([ASSIGNMENT, "assignment"], (eq, l, e), rv, k); //line 12114

This is a manual tree building statement. We do this in rare cases where the parser's default tree that is built is not suitable for our needs. By specifying the rule name with a following ! (as in assignment! on line 11992), the parser is told to bypass default tree building. If we want a tree returned, we will have to build it ourselves.

The ## is a shorthand to reference the root AST node of the subtree that will be returned by the current parser rule.

The #([ASSIGNMENT, "assignment"], ) creates a new node with a token type ASSIGNMENT and the token text "assignment".

Anything that appears after the comma is a list of child nodes that will be inserted, if they exist, in the left to right order they are specified in the grammar.

The (eq, l, e) creates a new sub-tree that has eq as the root node and 2 children, child 0 as l and child 1 as e.

The entire subtree rooted at eq will be inserted as the first child of the ASSIGNMENT node. This is the left side of the assignment operator, or the lvalue.

The rv (which is the rvalue for the assignment) and k (the no-error) will be the child 1 and child 2 respectively, if they actually exist.

Any node listed in this tree building syntax that does not exist is just silently ignored. It will not cause a parsing error.

(k:KW_NO_ERROR)?

The k: is a label that defines a local AST variable named k. In actions (the Java code in {} inserted inline with the rest of the grammar), this is named #k. But for regular grammar references, just k will work. The other variables are defined as labels for the other parts of the matched text. These can be single tokens or they can be the root node of a sub-tree.

Could you explain me what does the following statement mean:

  1. = #([ASSIGNMENT, "assignment"], (eq, l, e), rv, k); //line 12114

This is a manual tree building statement. We do this in rare cases where the parser's default tree that is built is not suitable for our needs. By specifying the rule name with a following ! (as in assignment! on line 11992), the parser is told to bypass default tree building. If we want a tree returned, we will have to build it ourselves.

The ## is a shorthand to reference the root AST node of the subtree that will be returned by the current parser rule.

The #([ASSIGNMENT, "assignment"], ) creates a new node with a token type ASSIGNMENT and the token text "assignment".

Anything that appears after the comma is a list of child nodes that will be inserted, if they exist, in the left to right order they are specified in the grammar.

The (eq, l, e) creates a new sub-tree that has eq as the root node and 2 children, child 0 as l and child 1 as e.

The entire subtree rooted at eq will be inserted as the first child of the ASSIGNMENT node. This is the left side of the assignment operator, or the lvalue.

The rv (which is the rvalue for the assignment) and k (the no-error) will be the child 1 and child 2 respectively, if they actually exist.

Any node listed in this tree building syntax that does not exist is just silently ignored. It will not cause a parsing error.

#30 Updated by Vadim Gindin over 10 years ago

Thank you for the explanation. I wrote an ast node in my previous comment (#28).

#31 Updated by Constantin Asofiei over 10 years ago

Vadim, to identify if the problem is in the parser, then is best to check the AST generated by the FRONT phase, as this is the pristine AST generated by the parser (plus the fixups). If you do this, you will notice that a current-window = h no-error. assignment looks like:

    <ast col="0" id="12884901924" line="0" text="assignment" type="ASSIGNMENT">
      <ast col="16" id="12884901925" line="4" text="=" type="ASSIGN">
        <ast col="1" id="12884901928" line="4" text="current-window" type="SYS_HANDLE">
          <annotation datatype="java.lang.Long" key="oldtype" value="507"/>
          <annotation datatype="java.lang.Long" key="tempidx" value="197"/>
        </ast>
        <ast col="0" id="12884901931" line="0" text="expression" type="EXPRESSION">
          <ast col="18" id="12884901932" line="4" text="h" type="VAR_HANDLE">
            <annotation datatype="java.lang.Long" key="oldtype" value="2348"/>
            <annotation datatype="java.lang.Long" key="refid" value="12884901891"/>
          </ast>
        </ast>
      </ast>
      <ast col="20" id="12884901935" line="4" text="no-error" type="KW_NO_ERROR"/>
    </ast>

and the NO-ERROR is emitted properly. The root cause I think is in the annotations/frame_scoping.rules like 4085:
      <!-- re-write CURRENT/ACTIVE/DEFAULT-WINDOW assignment to an expression, as this is no
           longer a valid assignment node -->
      <rule>parent.type == prog.assign and 
            type == prog.sys_handle    and
            (#(int) getNoteLong("oldtype") == prog.kw_cur_win or
             #(int) getNoteLong("oldtype") == prog.kw_act_win or
             #(int) getNoteLong("oldtype") == prog.kw_def_win)
         <action>node = copy.getNextSibling()</action>
         <action>node.move(copy, 0)</action>
         <action>node = copy.parent</action>
         <action>node.type = prog.expression</action>
         <action>node = copy.parent.parent</action>
         <action>copy.parent.putAnnotation("wasAssign", true)</action>
         <action>copy.parent.move(node.parent, node.indexPos)</action>
         <action>node.remove()</action>
      </rule>

#32 Updated by Vadim Gindin over 10 years ago

Thank you Constantin!

I ran the conversion process with f2+cb options and got my first result, but when I ran the conversion process only with f2 option I got the result - same as you have wrote. Why it is different? The docs saying that cb means

unreachable code, annotations, frame generator, base structure, core conversion and brew

I can only suspect that the transformation from assignment to expression is going in the annotation processing step. Isn't it?

Another one question: how did you find frame_scoping.rules block? Did you know that "somewhere in this file this block exists" or did you just use text search to find this block by string "kw_cur_win" for example?

#33 Updated by Constantin Asofiei over 10 years ago

Vadim Gindin wrote:

I can only suspect that the transformation from assignment to expression is going in the annotation processing step. Isn't it?

Correct, but add some printfln logging to the frame_scoping.rules code I mention to confirm.

Another one question: how did you find frame_scoping.rules block? Did you know that "somewhere in this file this block exists" or did you just use text search to find this block by string "kw_cur_win" for example?

There were two phases:
  1. confirm that progress.g emits the no-error clause properly (by checking the AST from the F2 phase).
  2. search the P2J project for prog.kw_cur_win and see where it is used. Fortunately, there were not many places using it, so it was easy to find the problematic rule.

#34 Updated by Vadim Gindin over 10 years ago

I corrected the rules block you specified to force it transfer KW_NO_ERROR too and got this ast node (after annotation processing):

    <ast col="16" id="1120986464286" line="8" text="=" type="EXPRESSION">
      <annotation datatype="java.lang.Boolean" key="wasassign" value="true"/>
      <annotation datatype="java.lang.Long" key="peerid" value="1159641169959"/>
      <ast col="1" id="1120986464289" line="8" text="current-window" type="SYS_HANDLE">
        <annotation datatype="java.lang.Long" key="oldtype" value="507"/>
        <annotation datatype="java.lang.Long" key="tempidx" value="197"/>
        <annotation datatype="java.lang.Long" key="peerid" value="1159641169960"/>
        <ast col="0" id="1120986464292" line="0" text="expression" type="EXPRESSION">
          <annotation datatype="java.lang.Long" key="peerid" value="1159641169961"/>
          <ast col="18" id="1120986464293" line="8" text="wh" type="VAR_HANDLE">
            <annotation datatype="java.lang.Long" key="oldtype" value="2348"/>
            <annotation datatype="java.lang.Long" key="refid" value="1120986464259"/>
            <annotation datatype="java.lang.Long" key="peerid" value="1159641169962"/>
          </ast>
        </ast>
      </ast>
      <ast col="21" id="1120986464296" line="8" text="no-error" type="KW_NO_ERROR"/>
    </ast>

It don't produce correct correspondent Java code for KW_NO_ERROR and looks not good intuitively. KW_NO_ERROR probably should not be included inside EXPRESSION. Am I right? The question is how this ast node should be to be correct and to produce correspondent Java code? May be it should be wrapped inside a statement node in this way:

  <ast type="statement">
    <ast type="expression">
      ...
    </ast>
    <ast col="21" id="1120986464296" line="8" text="no-error" type="KW_NO_ERROR"/>
  </ast>

Thank you.

#35 Updated by Constantin Asofiei over 10 years ago

KW_NO_ERROR probably should not be included inside EXPRESSION. Am I right? The question is how this ast node should be to be correct and to produce correspondent Java code?

I think you are on the right path, but the solution may be much simpler. Take a look at this rule in convert/language_statement.rules:95:

      <rule>
         (type == prog.statement and descendant(prog.kw_no_error, 4)) or
         (type == prog.assignment and descendant(prog.kw_no_error, 1))

         <action>
            createJavaAst(java.static_method_call,
                          "ErrorManager.silentErrorEnable",
                          closestPeerId)
         </action>      
      </rule>

This emits the silentErrorEnable call if the kw_no_error is a child of an assignment node or a 4-th level descendent of a statement node. I think is enough to add a check here for a type == prog.expression and descendant(prog.kw_no_error, 1) to properly emit it (same applies for the silentErrorDisable call on line 600).

#36 Updated by Vadim Gindin over 10 years ago

Yes It will be simpler. But It looks like the last change you propose is a solution of some private task. I added first change in the frame_scoping.rules to emit KW_NO_ERROR in a some place in the target node. I'm not sure that this place is correct. If I can think that it is correct than I can go further and add the next change that emits Java calls for this KW_NO_ERROR place. Are you sure that it is good solution?

#37 Updated by Constantin Asofiei over 10 years ago

Vadim Gindin wrote:

I added first change in the frame_scoping.rules to emit KW_NO_ERROR in a some place in the target node. I'm not sure that this place is correct.

After we rewrite this ASSIGNMENT to an expression, as you noticed, the KW_NO_ERROR was lost. Adding it as a child for the EXPRESSION node is OK, but for this to be emitted you need to explicitly treat this case too, in convert/language_statement.rules. I don't see a reason for complicating the AST (so that it will have a parent STATEMENT and the KW_NO_ERROR be emitted as a child for some inner node), so is easier to treat this custom case explicitly (as I mentioned in previous note). There are situations when we need to leverage between "do we complicate things further so that an existing rule should not be touched" and "do we change a rule and treat a custom case explicitly, as it proves much easier and straightforward to fix"; and I think this is a case where it's a lot easier to treat it explicitly, than complicating the AST.

#38 Updated by Vadim Gindin over 10 years ago

I understand, thank you. Now it produces this Java code:

ErrorManager.silentErrorEnable()setCurrentWindow(wh)ErrorManager.silentErrorDisable();

It seems it because KW_NO_ERROR is inside expression and unfortunately I forced to wrap EXPRESSION inside STATEMENT node. Isn't it? If so how to do it?

#39 Updated by Constantin Asofiei over 10 years ago

It seems it because KW_NO_ERROR is inside expression and unfortunately I forced to wrap EXPRESSION inside STATEMENT node. Isn't it? If so how to do it?

Hmm... yes, I think we need to wrap it in a statement node. The location for this fix is back in frame_scoping.rules. The rules at line 4092 look like this:

      <rule>parent.type == prog.assign and 
            type == prog.sys_handle    and
            (#(int) getNoteLong("oldtype") == prog.kw_cur_win or
             #(int) getNoteLong("oldtype") == prog.kw_act_win or
             #(int) getNoteLong("oldtype") == prog.kw_def_win)
         <action>node = copy.getNextSibling()</action>
         <action>node.move(copy, 0)</action>
         <action>node = copy.parent</action>
         <action>node.type = prog.expression</action>
         <action>node = copy.parent.parent</action>
         <action>copy.parent.putAnnotation("wasAssign", true)</action>
         <action>copy.parent.move(node.parent, node.indexPos)</action>
         <action>node.remove()</action>
      </rule>

The last two actions are moving the now-renamed ASSIGN node in the position of the ASSIGNMENT node and then remove the ASSIGNMENT node. I think will be enough to replace the last two rules with something like: node.type = prog.statement: node already points to ASSIGNMENT and this will rename it into a STATEMENT node.

If this works, post here the new AST.

#40 Updated by Vadim Gindin over 10 years ago

Yes it works and moreover there are no more need to move KW_NO_ERROR manually. Here is the new AST node:

    <ast col="0" id="1120986464285" line="0" text="statement" type="STATEMENT">
      <ast col="16" id="1120986464286" line="8" text="=" type="EXPRESSION">
        <annotation datatype="java.lang.Boolean" key="wasassign" value="true"/>
        <annotation datatype="java.lang.Long" key="peerid" value="1159641169960"/>
        <ast col="1" id="1120986464289" line="8" text="current-window" type="SYS_HANDLE">
          <annotation datatype="java.lang.Long" key="oldtype" value="507"/>
          <annotation datatype="java.lang.Long" key="tempidx" value="197"/>
          <annotation datatype="java.lang.Long" key="peerid" value="1159641169961"/>
          <ast col="0" id="1120986464292" line="0" text="expression" type="EXPRESSION">
            <annotation datatype="java.lang.Long" key="peerid" value="1159641169962"/>
            <ast col="18" id="1120986464293" line="8" text="wh" type="VAR_HANDLE">
              <annotation datatype="java.lang.Long" key="oldtype" value="2348"/>
              <annotation datatype="java.lang.Long" key="refid" value="1120986464259"/>
              <annotation datatype="java.lang.Long" key="peerid" value="1159641169963"/>
            </ast>
          </ast>
        </ast>
      </ast>
      <ast col="21" id="1120986464296" line="8" text="no-error" type="KW_NO_ERROR"/>
    </ast>

Produced Java code is correct.

#41 Updated by Constantin Asofiei over 10 years ago

Great. Please finish the changes I mentioned in note 27 (expect the current-window = ? case) and post the update here.

#42 Updated by Vadim Gindin over 10 years ago

Constantin, could you help me. I didn't find in ErrorManager a possibility to include in the error message the name of procedure. By the way Progress shows the full name of procedure file (including the path). Two questions:
1) How to find the procedure name (full name)?
2) Should I include it in the error message manually, or there is exists the way to do it in ErrorManager?

#43 Updated by Constantin Asofiei over 10 years ago

Vadim Gindin wrote:

Constantin, could you help me. I didn't find in ErrorManager a possibility to include in the error message the name of procedure. By the way Progress shows the full name of procedure file (including the path). Two questions:
1) How to find the procedure name (full name)?

4GL has the PROGRAM-NAME function, with PROGRAM-NAME(1) returning the full name of the currently executing program. This converts to EnvironmentOps.getSourceName - so you can use this to find the program name.

2) Should I include it in the error message manually, or there is exists the way to do it in ErrorManager?

The error must be included in the message manually.

#44 Updated by Vadim Gindin over 10 years ago

Thank you, but Progress shows full path to procedure file starting from root folder "/". EnvironmentOps.getSourceName(1) returns only winhandles/assign_current_window.p

#45 Updated by Constantin Asofiei over 10 years ago

Vadim Gindin wrote:

Thank you, but Progress shows full path to procedure file starting from root folder "/". EnvironmentOps.getSourceName(1) returns only winhandles/assign_current_window.p

Have you tested the program from command line, in 4GL? Also, to which error message do you refer, exactly? Because this case:

def var wh as handle.
current-window = wh.

shows this error: ** a.p: Unable to evaluate field for assignment. (143)

#46 Updated by Vadim Gindin over 10 years ago

Yes, I checked it again. My exact message is:
** /home/vig/winhandles/simple2.p: Unable to evaluate field for assignment. (143)

It seems it depends on exact command in Progress. I ran my script with full name /home/vig/winhandles/simple2.p and you probably added some directory to PROPATH variable and specified a.p from this directory. Isn't it?

#47 Updated by Constantin Asofiei over 10 years ago

I ran the program using pro -p a.p; if you run it using pro -p somefolder/a.p, then you will have somefolder/a.p reported. I think the full-path problem is a non-issue for us at this time, just report the program name as reported by the EnvironmentOps.getSourceName(1); this will do for now, make sure to add a comment that in some cases the full path is provided.

#48 Updated by Vadim Gindin over 10 years ago

Here is an update with last changes.

#49 Updated by Vadim Gindin over 10 years ago

Sorry I forgot to add the comment about the path. Here is updated archive.

#50 Updated by Constantin Asofiei over 10 years ago

Review of 0107a.zip:
  • please try not to post updates merged with other tasks; if you find it difficult to work more than one task in the same project, you can always use a second project to work the second task. This update doesn't even compile with rev 10427, and it makes it difficult to double-check any P2J runtime.
  • I don't see any changes for the ExternalProgramWrapper.currentWindow/setCurrentWindow APIs (i.e. this-procedure:current-window assignment and access) - have you tested this?
  • for the Unable to assign widget to CURRENT-WINDOW. (3130) message: you need to set the prefix flag for the ErrorManager.recordOrThrowError to false, to not emit the ** prefix... as I recall, this message is not prefixed.

#51 Updated by Vadim Gindin over 10 years ago

Sorry, I forgot about this-procedure:current-window. Here is the test:

def var wh as widget-handle.

if this-procedure:current-window <> ? then 
   message "this-procedure:current-window is unexpected - " this-procedure:current-window.

/* outputs following error: **Unable to assign UNKNOWN value to attribute CURRENT-WINDOW of PROCEDURE WIDGET. (4083) */
/*this-procedure:current-window = wh.*/

/* outputs following error: **Unable to set attribute CURRENT-WINDOW for PROCEDURE widget. (4708) */
/*create button  wh.
this-procedure:current-window = wh.*/

this-procedure:current-window = active-window.
if this-procedure:current-window <> active-window then
   message "this-procedure:current-window was not changed ".

Interesting results.
1. Default value of this-procedure:current-window is ? as documented.
2. When assigned value is ? or invalid Progress shows an error:
**Unable to assign UNKNOWN value to attribute CURRENT-WINDOW of PROCEDURE WIDGET. (4083)
3. When assigned value is valid handle but handle of widget other than window Progress shows an error:
**Unable to set attribute CURRENT-WINDOW for PROCEDURE widget. (4708)
4. If assigned value is correct window handle - this-procedure:current-window attribute takes the value of it. It differs from current-window handle.

#52 Updated by Vadim Gindin over 10 years ago

Here is an update with last changes. I merged it with current revision and checked if it is ok again. If I correctly understand here should be no compilation errors. I also removed from this update other changes interfering with it. Hope it will be ok.

#53 Updated by Constantin Asofiei over 10 years ago

Review for 0108a.zip:
  • In files where the history entry is from 2014, update the copyright years in the file's header.
  • LogicalTerminal:8629 - you have some tab characters. In Eclipse, you can enable visible white-spaces, as sometimes Eclipse inserts tabs instead of spaces.
  • LT.setProcCurrentWindow doesn't need to validate the phandle (as it is always called on a valid phandle), but please leave behind a TODO:, as in GUI mode we may need some implementation. Same for LT.currentWindow(handle).
  • LT.currentWindow: phandle.getResource() returns the ExternalProgramWrapper, not the referent. The referent is retrieved via phandle.get(). Same in LT.setProcCurrentWindow(). I'm curious why you didn't got a NPE during testing...
  • ProcedureManager.getCurrentWindow - always return a copy of the handle, never expose the saved reference to outside code.
  • ProcedureManager.setCurrentWindow: the code should have been locateProcedure(referent).currentWindow.assign(winHandle); not locateProcedure(referent).currentWindow = winHandle;, which saved the outside reference.
  • ProcedureManager - you've added an extra line after ContextContainer inner class...
  • ExternalProgramWrapper.currentWindow - change PersistentProcedure.currentWindow signature to return a handle instead of WindowWidget. This will be consistent with how legacy resources are exposed to the outside world in P2J (always via handles).

#54 Updated by Vadim Gindin over 10 years ago

Next update with last changes.

#55 Updated by Constantin Asofiei over 10 years ago

Go ahead and get it tested. Before committing, fix the tab characters in LT.setProcCurrentWindow:8627.

#56 Updated by Constantin Asofiei over 10 years ago

Vadim, on note 24 you mentioned that "window is unknown:" in batch mode. You forgot to implement this case in LT.currentWindow() and other APIs.

#57 Updated by Vadim Gindin over 10 years ago

You're right.. Now I'm trying to implement it (batch-mode support) and I'm getting following problem. CURRENT-WINDOW in batch-mode has unknown value and my test does following:

def var w as int.
w = current-window:width.
current-window:width = 101.

It will be converted to following Java code:

w.assign(handle.unwrapSizeable(currentWindow()).getWidthChars());
handle.unwrapSizeable(currentWindow()).setWidthChars(new integer(101));

currentWindow() in my implementation will return new handle(). For this value handle.unwrapSizeable(..) method will consider it as invalid handle and will return proxy object that outputs 2 messages:

Invalid handle. Not initialized or points to a deleted object (3135)
Cannot access the WIDTH-CHARS attribute because the widget does not exist (3140)

Problems:
1) Java outputs 2 messages independently of current usage of invalid handle. But Progress in my testcase returns only the second message. Should I change this common behavior of hande or I should make a custom behavior for this case. Is yes - how to do it?
2) Attribute name is WIDTH-CHARS, but Progress outputs WIDTH. I suspect it is the same because there are no setWidth() method in Sizable. As I can understand the attribute name is got from LegacyAttribute annotation of method getWidthChars() and so we are getting WIDTH-CHARS. How to get just WIDTH attribute name?

#58 Updated by Constantin Asofiei over 10 years ago

I understand the problem. Unfortunately, I think this will need conversion changes, to let the handle.unwrap call know that this is a window system handle (or some other modality to inform the runtime). For now, limit on checking that the window system handles and procedure:current-window are reported correctly in batch mode (using valid-handle and unknown equality tests).

Greg: we can add a low-priority task for this problem, as this looks like an exotic case.

2) Attribute name is WIDTH-CHARS, but Progress outputs WIDTH. I suspect it is the same because there are no setWidth() method in Sizable. As I can understand the attribute name is got from LegacyAttribute annotation of method getWidthChars() and so we are getting WIDTH-CHARS. How to get just WIDTH attribute name?

This suggests that the LegacyAttribute annotation should be enhanced to record the name used in error message, beside the real attribute name. Document this problem in #2194.

#59 Updated by Greg Shah over 10 years ago

Greg: we can add a low-priority task for this problem, as this looks like an exotic case.

OK.

2) Attribute name is WIDTH-CHARS, but Progress outputs WIDTH. I suspect it is the same because there are no setWidth() method in Sizable. As I can understand the attribute name is got from LegacyAttribute annotation of method getWidthChars() and so we are getting WIDTH-CHARS. How to get just WIDTH attribute name?

This suggests that the LegacyAttribute annotation should be enhanced to record the name used in error message, beside the real attribute name. Document this problem in #2194.

Actually, I think this is just a consequence of some ridiculous keyword abbreviation + ambiguity in the 4GL.

The 4GL docs report both as valid keywords: WIDTH (non-reserved keyword with no abbreviations) and WIDTH-CHARS (non-reserved keyword, with minimum abbreviation as WIDTH). The obvious problem here is that by this definition, there is no way to tell whether WIDTH is WIDTH or WIDTH-CHARS. In fact, we have even coded it as a minimum abbreviation of WIDTH- in order to differentiate the two cases.

Annoyingly, WIDTH and WIDTH-CHARS are both used in actual syntax diagrams throughout the docs, without ever suggesting that these are synonyms. But the 4GL itself definitely treats these two as synonyms in many (if not all) places. WIDTH-CHARS is only specified as an attribute name in the docs. But WIDTH can be used in this attribute case and it is treated as WIDTH-CHARS (as synonyms). We also know that WIDTH-CHARS can be used instead of WIDTH in a frame phrase (this is undocumented). What we have not yet tested is whether WIDTH-CHARS can be used anywhere else that WIDTH is specified in the docs. It is very likely that WIDTH-CHARS is really just a longer form of WIDTH and the two are completely interchangeable. But we won't know that without further testing.

Is there ever any way the 4GL can report WIDTH-CHARS as the attribute name? If not, then let's just code it as WIDTH and we are done.

#60 Updated by Constantin Asofiei over 10 years ago

Greg Shah wrote:

Is there ever any way the 4GL can report WIDTH-CHARS as the attribute name? If not, then let's just code it as WIDTH and we are done.

What I checked is the oposite: if the WIDTH attribute can be queried for a window handle:

def var h as handle.
h = current-window.

message h:width h:width-chars.
message can-query(h, "width") can-query(h, "width-chars").

this outputs:
80 80
yes yes

The attribute name, when the 3140 error message is displayed, P2J computes it from the Legacy annotations. And there we can specify only one name... This complicates things as can-query needs to handle both names. We can choose to set the name displayed in the error message at LegacyAttribute annotation and change the CAN-QUERY/CAN-SET implementation to handle known aliases (not abbreviations) for a certain attribute.

#61 Updated by Greg Shah over 10 years ago

We can choose to set the name displayed in the error message at LegacyAttribute annotation and change the CAN-QUERY/CAN-SET implementation to handle known aliases (not abbreviations) for a certain attribute.

This sounds reasonable.

#62 Updated by Vadim Gindin over 10 years ago

Here is the update with batch-mode support added.

#63 Updated by Constantin Asofiei over 10 years ago

  • LogicalTerminal.setCurrentWindow(handle h) - have you tested the assignment using the NO-ERROR clause too? Because I think you are missing return statements in the first two if blocks:
          if (h == null || !h._isValid() || h.isUnknown())
          {
             // proc can be full name with path of procedure file or relative.
             String proc = EnvironmentOps.getSourceName(1).getValue();
             String ms = proc + ": Unable to evaluate field for assignment";
             ErrorManager.recordOrThrowError(143, ms);
    
             return;
          }
    
          if (!(h.getResource() instanceof WindowWidget))
          {
             String ms = "Unable to assign widget  to CURRENT-WINDOW";
             ErrorManager.recordOrThrowError(3130, ms, false);
    
             return;
          }
    

    Same for LogicalTerminal.setProcCurrentWindow.
  • ExternalProgramWrapper.currentWindow and ExternalProgramWrapper.setCurrentWindow - is the behaviour for batch mode implemented properly?

#64 Updated by Vadim Gindin over 10 years ago

Constantin Asofiei wrote:

  • LogicalTerminal.setCurrentWindow(handle h) - have you tested the assignment using the NO-ERROR clause too? Because I think you are missing return statements in the first two if blocks:
    [...]
    Same for LogicalTerminal.setProcCurrentWindow.

Yes I did test it but my tests did not allow me to find this issue. It probably need to test it on GUI for it. But you are right of course ). I added return to these methods and to ExternalProgramWrapper methods too.

  • ExternalProgramWrapper.currentWindow and ExternalProgramWrapper.setCurrentWindow - is the behaviour for batch mode implemented properly?

Not exactly. I retested it again and found out that the Progress does not set error-status:error flag when no-error is used. This problem does not interferes with batch-mode. This mode supported properly. The only difference in behavior is that the values are ?.

Please take a look at new update (merged with the last revision).

#65 Updated by Constantin Asofiei over 10 years ago

Vadim Gindin wrote:

Yes I did test it but my tests did not allow me to find this issue. It probably need to test it on GUI for it. But you are right of course ). I added return to these methods and to ExternalProgramWrapper methods too.

GUI has nothing to do with testing this. In batch or not, the test needs to look like:

def var h as handle.

output to foo.txt.
do on error undo,leave:
  current-window = h.
   message "no error raised".
end.

current-window = h no-error.

message error-status:error error-status:num-messages error-status:get-message(1).

This will show you if error condition is raised and the exact error message. Expand this test for the other window handles to confirm their behaviour, as I don't see tests for this in uast/winhandles.

  • ExternalProgramWrapper.currentWindow and ExternalProgramWrapper.setCurrentWindow - is the behaviour for batch mode implemented properly?

Not exactly. I retested it again and found out that the Progress does not set error-status:error flag when no-error is used. This problem does not interferes with batch-mode. This mode supported properly. The only difference in behavior is that the values are ?.

A test like this:

def var h as handle.

output to bar.txt.

do on error undo,leave:
this-procedure:current-window = h.
message "no error raised".
end.

this-procedure:current-window = h.
message error-status:error error-status:num-messages error-status:get-message(1). 
output close.

Shows that your assumption is correct - no error is raised. But an error message does get displayed:
**Unable to assign UNKNOWN value to attribute CURRENT-WINDOW on PROCEDURE widget. (4083)
no error raised
**Unable to assign UNKNOWN value to attribute CURRENT-WINDOW on PROCEDURE widget. (4083)
no 0

Use the ErrorManager.displayErrorRedirected to display the message on the terminal (for interactive mode) or to file (for redirected mode).

#66 Updated by Vadim Gindin over 10 years ago

Constantin,

I've committed tests I have for this task. I already have similar tests. Could you comment, why do you insist on the block do on error ... end?

About the method ErrorManager.displayErrorRedirected. Is it preferable than ErrorManager.recordOrShowError(4078, msg, false, false, false);?

#67 Updated by Constantin Asofiei over 10 years ago

Sorry, my bad. The test was missing a no-error clause for the last this-procedure:current-window = h. assignment; so is OK to use recordOrShowError, as you noted. The idea for displayErrorRedirected was to not add the message to the ErrorManager's error list, but my assumption was incorrect.

Why do I insist on DO... ON ERROR? This is the best way to determine if an ERROR condition is raised or not. We can't rely only on ERROR-STATUS:ERROR flag (checked after using NO-ERROR). I've learned to double check everything in 4GL, as sometimes you can get behaviour not matching the documentation or even common sense.

#68 Updated by Constantin Asofiei over 10 years ago

As Vadim N. noted on #1655 note 63: the problem we have with WIDTH and WIDTH-CHARS can be found with HEIGHT and HEIGHT-CHARS too.

#69 Updated by Vadim Gindin over 10 years ago

So I tested it again. It works. I'm going to run regression testing.

#70 Updated by Constantin Asofiei over 10 years ago

OK, place the final update here for review, before releasing it.

#71 Updated by Vadim Gindin over 10 years ago

There is no changes since last update vig_upd20140116a.zip

#72 Updated by Constantin Asofiei over 10 years ago

Great, you can release 0116a.zip after it passes testing.

#73 Updated by Vadim Gindin over 10 years ago

vig_upd20140116a.zip passed regression testing. Committed as rev #10443.

#74 Updated by Greg Shah over 10 years ago

  • Status changed from New to Closed

ChUI and batch support is complete, which is sufficient for M7. GUI support will be implemented in #2229.

#75 Updated by Greg Shah over 7 years ago

  • Target version changed from Milestone 7 to Runtime Support for Server Features

Also available in: Atom PDF