Bug #4427
Unable to convert keyword input when used to index into an extent
100%
History
#1 Updated by Roger Borrello over 4 years ago
General¶
Expression execution error when there is an input
statement withing the brackets of an extent which is also the parameter to another input
. If you remove the first input
, we are successful.
Update: Committed rules/annotations/input_builtin_prep.rules
to 4207a-11367.Update: This still has work to do, as the Java produced does not compile. See #note-11
Update: Fixed in 4207a-11349.
P2J Branch¶
This is being handled in Branch 4207a
Testcase¶
Checked into testcase_repo
:uast/extent_subscript_using_input.p
def buffer mybuff for Person. form mybuff.schedule[1] mybuff.schedule[2] mybuff.schedule[3] mybuff.schedule[4] mybuff.schedule[5] mybuff.emp-num with frame myframe. find first mybuff no-error. if not available mybuff then create mybuff. do with frame myframe: do while true: update mybuff.schedule[1] mybuff.schedule[2] mybuff.schedule[3] mybuff.schedule[4] mybuff.schedule[5] mybuff.emp-num edit-loop: editing: readkey. if input schedule[input emp-num] = "" then message "number not in use". else message "number in use". end. end. end.
Artifacts¶
Execution Log¶
[java] ------------------------------------------------------------------------------ [java] Core Code Conversion [java] ------------------------------------------------------------------------------ [java] [java] Optional rule set [customer_specific_conversion] not found. [java] ./abl/extent_subscript_using_input.p [java] Elapsed job time: 00:00:00.964 [java] EXPRESSION EXECUTION ERROR: [java] --------------------------- [java] throwException(errmsg, this) [java] ^ { Unsupported builtin function KW_INPUT. [FUNC_POLY id <197568495865> 28:25] } [java] --------------------------- [java] ERROR: [java] com.goldencode.p2j.pattern.TreeWalkException: ERROR! Active Rule: [java] ----------------------- [java] RULE REPORT [java] ----------------------- [java] Rule Type : WALK [java] Source AST: [ input ] BLOCK/INNER_BLOCK/BLOCK/INNER_BLOCK/BLOCK/STATEMENT/KW_UPDATE/EDITING_BLOCK/BLOCK/STATEMENT/KW_IF/EXPRESSION/EQUALS/FUNC_POLY/LBRACKET/FUNC_POLY/ @28:25 {197568495865} [java] Copy AST : [ input ] BLOCK/INNER_BLOCK/BLOCK/INNER_BLOCK/BLOCK/STATEMENT/KW_UPDATE/EDITING_BLOCK/BLOCK/STATEMENT/KW_IF/EXPRESSION/EQUALS/FUNC_POLY/LBRACKET/FUNC_POLY/ @28:25 {197568495865} [java] Condition : throwException(errmsg, this) [java] Loop : false [java] --- END RULE REPORT --- [java] [java] [java] [java] at com.goldencode.p2j.pattern.PatternEngine.run(PatternEngine.java:1070) [java] at com.goldencode.p2j.convert.TransformDriver.processTrees(TransformDriver.java:542) [java] at com.goldencode.p2j.convert.ConversionDriver.back(ConversionDriver.java:580) [java] at com.goldencode.p2j.convert.TransformDriver.executeJob(TransformDriver.java:876) [java] at com.goldencode.p2j.convert.ConversionDriver.main(ConversionDriver.java:983) [java] Caused by: com.goldencode.expr.ExpressionException: Expression execution error @1:1 [FUNC_POLY id=197568495865] [java] at com.goldencode.p2j.pattern.AstWalker.walk(AstWalker.java:275) [java] at com.goldencode.p2j.pattern.AstWalker.walk(AstWalker.java:210) [java] at com.goldencode.p2j.pattern.PatternEngine.apply(PatternEngine.java:1633) [java] at com.goldencode.p2j.pattern.PatternEngine.processAst(PatternEngine.java:1531) [java] at com.goldencode.p2j.pattern.PatternEngine.processAst(PatternEngine.java:1479) [java] at com.goldencode.p2j.pattern.PatternEngine.run(PatternEngine.java:1034) [java] ... 4 more [java] Caused by: com.goldencode.expr.ExpressionException: Expression execution error @1:1 [java] at com.goldencode.expr.Expression.execute(Expression.java:484) [java] at com.goldencode.p2j.pattern.Rule.apply(Rule.java:497) [java] at com.goldencode.p2j.pattern.Rule.executeActions(Rule.java:745) [java] at com.goldencode.p2j.pattern.Rule.coreProcessing(Rule.java:712) [java] at com.goldencode.p2j.pattern.Rule.apply(Rule.java:534) [java] at com.goldencode.p2j.pattern.Rule.executeActions(Rule.java:745) [java] at com.goldencode.p2j.pattern.Rule.coreProcessing(Rule.java:712) [java] at com.goldencode.p2j.pattern.Rule.apply(Rule.java:534) [java] at com.goldencode.p2j.pattern.Rule.executeActions(Rule.java:745) [java] at com.goldencode.p2j.pattern.Rule.coreProcessing(Rule.java:712) [java] at com.goldencode.p2j.pattern.Rule.apply(Rule.java:534) [java] at com.goldencode.p2j.pattern.RuleContainer.apply(RuleContainer.java:585) [java] at com.goldencode.p2j.pattern.RuleSet.apply(RuleSet.java:98) [java] at com.goldencode.p2j.pattern.RuleContainer.apply(RuleContainer.java:585) [java] at com.goldencode.p2j.pattern.RuleSet.apply(RuleSet.java:98) [java] at com.goldencode.p2j.pattern.AstWalker.walk(AstWalker.java:262) [java] ... 9 more [java] Caused by: com.goldencode.p2j.pattern.CommonAstSupport$UserGeneratedException: Unsupported builtin function KW_INPUT. [FUNC_POLY id <197568495865> 28:25] [java] at com.goldencode.p2j.pattern.CommonAstSupport$Library.throwException(CommonAstSupport.java:2817) [java] at com.goldencode.expr.CE12445.execute(Unknown Source) [java] at com.goldencode.expr.Expression.execute(Expression.java:391) [java] ... 24 more BUILD FAILED
AST Snippet¶
<ast col="7" id="197568495778" line="28" text="if" type="KW_IF"> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <ast col="0" id="197568495780" line="0" text="expression" type="EXPRESSION"> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <ast col="40" id="197568495781" line="28" text="=" type="EQUALS"> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <ast col="10" id="197568495785" line="28" text="input" type="FUNC_POLY"> <annotation datatype="java.lang.Long" key="oldtype" value="691"/> <annotation datatype="java.lang.Boolean" key="builtin" value="true"/> <annotation datatype="java.lang.Boolean" key="returnsunknown" value="false"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <annotation datatype="java.lang.Long" key="frame-id" value="197568495829"/> <annotation datatype="java.lang.String" key="methodtxt" value="getScheduleArray"/> <ast col="16" hidden="true" id="197568495787" line="28" text="schedule" type="FIELD_CHAR"> <annotation datatype="java.lang.Long" key="oldtype" value="2781"/> <annotation datatype="java.lang.String" key="schemaname" value="p2j_test.person.schedule"/> <annotation datatype="java.lang.String" key="bufname" value="p2j_test.mybuff"/> <annotation datatype="java.lang.String" key="dbname" value="p2j_test"/> <annotation datatype="java.lang.Long" key="recordtype" value="12"/> <annotation datatype="java.lang.String" key="name" value="schedule"/> <annotation datatype="java.lang.Long" key="type" value="402"/> <annotation datatype="java.lang.String" key="format" value=""x(64)""/> <annotation datatype="java.lang.Long" key="extent" value="5"/> <annotation datatype="java.lang.Long" key="param_index" value="0"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <annotation datatype="java.lang.Boolean" key="is_meta" value="false"/> <annotation datatype="java.lang.String" key="fieldname" value="schedule"/> <annotation datatype="java.lang.String" key="bufrefkey" value="p2j_test.person,p2j_test.mybuff,197568495627"/> <annotation datatype="java.lang.Long" key="bufreftype" value="18"/> <annotation datatype="java.lang.String" key="uniquename" value="p2j_test.mybuff_p2j_test.person"/> <annotation datatype="java.lang.String" key="methodtxt" value="getSchedule"/> <annotation datatype="java.lang.String" key="check_accessors" value=""/> <annotation datatype="java.lang.Boolean" key="dynamicindex" value="true"/> <annotation datatype="java.lang.String" key="getter" value="getScheduleArray"/> <annotation datatype="java.lang.String" key="setter" value="setScheduleArray"/> <annotation datatype="java.lang.String" key="javaname" value="scheduleArray"/> <annotation datatype="java.lang.String" key="accessor" value="widgetScheduleArray"/> <annotation datatype="java.lang.String" key="widgettype" value="FillInWidget"/> <annotation datatype="java.lang.Long" key="frame-id" value="197568495829"/> <ast col="24" id="197568495788" line="28" text="[" type="LBRACKET"> <annotation datatype="java.lang.Boolean" key="emit" value="false"/> <ast col="25" id="197568495789" line="28" text="input" type="FUNC_POLY"> <annotation datatype="java.lang.Long" key="oldtype" value="691"/> <annotation datatype="java.lang.Boolean" key="builtin" value="true"/> <annotation datatype="java.lang.Boolean" key="returnsunknown" value="false"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <annotation datatype="java.lang.Long" key="frame-id" value="197568495829"/> <annotation datatype="java.lang.String" key="methodtxt" value="getEmpNum"/> <ast col="31" hidden="true" id="197568495791" line="28" text="emp-num" type="FIELD_INT"> <annotation datatype="java.lang.Long" key="oldtype" value="2781"/> <annotation datatype="java.lang.String" key="schemaname" value="p2j_test.person.emp-num"/> <annotation datatype="java.lang.String" key="bufname" value="p2j_test.mybuff"/> <annotation datatype="java.lang.String" key="dbname" value="p2j_test"/> <annotation datatype="java.lang.Long" key="recordtype" value="12"/> <annotation datatype="java.lang.String" key="name" value="emp-num"/> <annotation datatype="java.lang.Long" key="type" value="410"/> <annotation datatype="java.lang.String" key="format" value=""9999999""/> <annotation datatype="java.lang.String" key="columnlabel" value=""Emp Num Column""/> <annotation datatype="java.lang.Long" key="param_index" value="0"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <annotation datatype="java.lang.Boolean" key="is_meta" value="false"/> <annotation datatype="java.lang.String" key="fieldname" value="empNum"/> <annotation datatype="java.lang.String" key="bufrefkey" value="p2j_test.person,p2j_test.mybuff,197568495627"/> <annotation datatype="java.lang.Long" key="bufreftype" value="18"/> <annotation datatype="java.lang.String" key="uniquename" value="p2j_test.mybuff_p2j_test.person"/> <annotation datatype="java.lang.String" key="methodtxt" value="getEmpNum"/> <annotation datatype="java.lang.String" key="check_accessors" value=""/> <annotation datatype="java.lang.String" key="getter" value="getEmpNum"/> <annotation datatype="java.lang.String" key="setter" value="setEmpNum"/> <annotation datatype="java.lang.String" key="javaname" value="empNum"/> <annotation datatype="java.lang.String" key="accessor" value="widgetEmpNum"/> <annotation datatype="java.lang.String" key="widgettype" value="FillInWidget"/> <annotation datatype="java.lang.Long" key="frame-id" value="197568495829"/> </ast> </ast> </ast> </ast> <ast col="24" id="197568495864" line="28" text="[" type="LBRACKET"> <annotation datatype="java.lang.Boolean" key="emit" value="false"/> <ast col="25" id="197568495865" line="28" text="input" type="FUNC_POLY"> <annotation datatype="java.lang.Long" key="oldtype" value="691"/> <annotation datatype="java.lang.Boolean" key="builtin" value="true"/> <annotation datatype="java.lang.Boolean" key="returnsunknown" value="false"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <annotation datatype="java.lang.Long" key="frame-id" value="197568495829"/> <ast col="31" id="197568495866" line="28" text="emp-num" type="FIELD_INT"> <annotation datatype="java.lang.Long" key="oldtype" value="2781"/> <annotation datatype="java.lang.String" key="schemaname" value="p2j_test.person.emp-num"/> <annotation datatype="java.lang.String" key="bufname" value="p2j_test.mybuff"/> <annotation datatype="java.lang.String" key="dbname" value="p2j_test"/> <annotation datatype="java.lang.Long" key="recordtype" value="12"/> <annotation datatype="java.lang.String" key="name" value="emp-num"/> <annotation datatype="java.lang.Long" key="type" value="410"/> <annotation datatype="java.lang.String" key="format" value=""9999999""/> <annotation datatype="java.lang.String" key="columnlabel" value=""Emp Num Column""/> <annotation datatype="java.lang.Long" key="param_index" value="0"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <annotation datatype="java.lang.Boolean" key="is_meta" value="false"/> <annotation datatype="java.lang.String" key="fieldname" value="empNum"/> <annotation datatype="java.lang.String" key="bufrefkey" value="p2j_test.person,p2j_test.mybuff,197568495627"/> <annotation datatype="java.lang.Long" key="bufreftype" value="18"/> <annotation datatype="java.lang.String" key="uniquename" value="p2j_test.mybuff_p2j_test.person"/> <annotation datatype="java.lang.String" key="methodtxt" value="getEmpNum"/> <annotation datatype="java.lang.String" key="check_accessors" value=""/> <annotation datatype="java.lang.String" key="getter" value="getEmpNum"/> <annotation datatype="java.lang.String" key="setter" value="setEmpNum"/> <annotation datatype="java.lang.String" key="javaname" value="empNum"/> <annotation datatype="java.lang.String" key="accessor" value="widgetEmpNum"/> <annotation datatype="java.lang.String" key="widgettype" value="FillInWidget"/> <annotation datatype="java.lang.Long" key="frame-id" value="197568495829"/> </ast> </ast> </ast> </ast> <ast col="42" id="197568495792" line="28" text="""" type="STRING"> <annotation datatype="java.lang.Boolean" key="is-literal" value="true"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> </ast> </ast> </ast> <ast col="45" id="197568495794" line="28" text="then" type="KW_THEN"> <ast col="0" id="197568495796" line="0" text="block" type="BLOCK"> <annotation datatype="java.lang.Boolean" key="recordscoping" value="false"/> <ast col="0" id="197568495797" line="0" text="statement" type="STATEMENT"> <ast col="9" id="197568495798" line="29" text="message" type="KW_MSG"> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <ast col="0" id="197568495800" line="0" text="" type="CONTENT_ARRAY"> <ast col="0" id="197568495801" line="0" text="expression" type="EXPRESSION"> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <ast col="17" id="197568495802" line="29" text=""number not in use"" type="STRING"> <annotation datatype="java.lang.Boolean" key="is-literal" value="true"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> </ast> </ast> </ast> </ast> </ast> </ast> </ast> <ast col="7" id="197568495805" line="30" text="else" type="KW_ELSE"> <ast col="0" id="197568495807" line="0" text="block" type="BLOCK"> <annotation datatype="java.lang.Boolean" key="recordscoping" value="false"/> <ast col="0" id="197568495808" line="0" text="statement" type="STATEMENT"> <ast col="9" id="197568495809" line="31" text="message" type="KW_MSG"> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <ast col="0" id="197568495811" line="0" text="" type="CONTENT_ARRAY"> <ast col="0" id="197568495812" line="0" text="expression" type="EXPRESSION"> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> <ast col="17" id="197568495813" line="31" text=""number in use"" type="STRING"> <annotation datatype="java.lang.Boolean" key="is-literal" value="true"/> <annotation datatype="java.lang.Long" key="support_level" value="16400"/> </ast> </ast> </ast> </ast> </ast> </ast> </ast> </ast>
#3 Updated by Roger Borrello over 4 years ago
I cannot duplicate the issue using 4207a-11342 using the testcase nor customer code.
#4 Updated by Roger Borrello over 4 years ago
Roger Borrello wrote:
I cannot duplicate the issue using 4207a-11342 using the testcase nor customer code.
Here is the Java that is generated. It doesn't look like I would expect, although I'm a little green in this area.
package com.goldencode.testcases.abl; import com.goldencode.p2j.util.*; import com.goldencode.testcases.ui.abl.*; import com.goldencode.p2j.ui.*; import com.goldencode.p2j.persist.*; import com.goldencode.testcases.dmo.p2j_test.*; import com.goldencode.p2j.persist.lock.*; import static com.goldencode.p2j.util.BlockManager.*; import static com.goldencode.p2j.util.logical.*; import static com.goldencode.p2j.util.ErrorManager.*; /** * Business logic (converted to Java from the 4GL source code * in abl/extent_subscript_using_input.p). */ public class ExtentSubscriptUsingInput { Person.Buf mybuff = RecordBuffer.define(Person.Buf.class, "p2j_test", "mybuff", "mybuff"); ExtentSubscriptUsingInputMyframe myframeFrame = GenericFrame.createFrame(ExtentSubscriptUsingInputMyframe.class, "myframe"); /** * External procedure (converted to Java from the 4GL source code * in abl/extent_subscript_using_input.p). */ public void execute() { externalProcedure(ExtentSubscriptUsingInput.this, TransactionType.FULL, new Block((Body) () -> { myframeFrame.openScope(); RecordBuffer.openScope(mybuff); silent(() -> new FindQuery(mybuff, (String) null, null, "mybuff.siteId asc, mybuff.empNum asc").first()); if (_not(mybuff.available())) { mybuff.create(); } doBlock("blockLabel0", new Block((Body) () -> { loopLabel0: while (true) { } })); })); } }
#5 Updated by Greg Shah over 4 years ago
It is missing all output for this:
update mybuff.schedule[1] mybuff.schedule[2] mybuff.schedule[3] mybuff.schedule[4] mybuff.schedule[5] mybuff.emp-num edit-loop: editing: readkey. if input schedule[input emp-num] = "" then message "number not in use". else message "number in use". end. end.
This is a regression from my changes in rev 11342.
#6 Updated by Greg Shah over 4 years ago
The regression is fixed in rev 11343. Now this testcase fails again. Success!
#7 Updated by Roger Borrello over 4 years ago
This same testcase has the issue, so buffers are not the only thing leading to it. It could be 2 separate issues, or both the same root-cause.
define variable mybuff as character extent 1 no-undo. define variable mynum as integer no-undo. form mybuff[1] mynum with frame myframe. do with frame myframe: do while true: update mybuff[1] mynum edit-loop: editing: readkey. if input mybuff[input mynum] = "" then message "number not in use". else message "number in use". end. end. end.
#8 Updated by Roger Borrello over 4 years ago
Roger Borrello wrote:
In order to determine what is wrong, I created 2 separate testcases.This same testcase has the issue, so buffers are not the only thing leading to it. It could be 2 separate issues, or both the same root-cause.
[...]
extent_subscript_using_input/extent_subscript_using_input.p
- Just uses variablesextent_subscript_using_input/extent_subscript_using_input-buffer.p
- Uses a buffer
The end results is 2 ast files that have the same issue.
FUNC_POLY (input) will have either FIELD_CHAR (schedule) or VAR_CHAR (mybuff) as children. Those children will both have LBRACKET -> FUNC_POLY (input) as children, with subsequent FIELD_INT (emp-num) or VAR_INT (mynum) as children.
Both cases, there is another LBRACKET -> FUNC_POLY (input) with subsequent FIELD_INT (emp-num) or VAR_INT (mynum) as an additional parameter to the original FUNC_POLY (input).
Still investigating.
#9 Updated by Roger Borrello over 4 years ago
This has been fixed in 4207a-11349
#10 Updated by Roger Borrello over 4 years ago
- Estimated time set to 16.00
- Status changed from New to WIP
- % Done changed from 0 to 100
#11 Updated by Roger Borrello over 4 years ago
This still is not fixed, as the java code does not compile. Below is the compilation error of the testcase:
[javac] testcases/uast/uast/buildarea/src/com/goldencode/testcases/abl/ExtentSubscriptUsingInput.java:45: error: method getMynum in interface ExtentSubscriptUsingInputMyframe cannot be applied to given types; [javac] if (_isEqual(myframeFrame.getMybuffArray((myframeFrame.getMynum(myframeFrame.widgetMynum())).subscript()), "")) [javac] ^ [javac] required: no arguments [javac] found: FillInWidget [javac] reason: actual and formal argument lists differ in length
#12 Updated by Roger Borrello over 4 years ago
I looked at a much simpler case of using input mynum
then input mybuff[mynum]
instead of the more complicated, nested case input mybuff[input mynum]]
.
The generated Java compiled:
updateEditing(myframeFrame, elementList0, "editingLabel0", new Block((Body) () -> { KeyReader.readKey(); myframeFrame.getMynum(); if (_isEqual(myframeFrame.getMybuffArray((mynum).subscript()), ""))
Trying to simplify it one more layer, and just using input mybuff[1]
generated Java using the more direct myframeFrame.getMybuffArray0()
instead of the (mynum).subscript() method, so that didn't help.
The generated code from input mybuff[input mynum]
becomes:
updateEditing(myframeFrame, elementList0, "editingLabel0", new Block((Body) () -> { KeyReader.readKey(); if (_isEqual(myframeFrame.getMybuffArray((myframeFrame.getMynum(myframeFrame.widgetMynum())).subscript()), ""))
I'm wondering why the inner [input mynum]
did not result in myframeFrame.getMynum()
like it did when it was on its own line. Instead it became myframeFrame.widgetMynum()
which was passed as a parameter to the myframeFrame.getMynum()
method. That method doesn't take a parameter.
The correct code should be myframeFrame.getMybuffArray(((myframeFrame.getMynum()).subscript()))
shouldn't it? It compiles, in any case.
#13 Updated by Roger Borrello over 4 years ago
Roger Borrello wrote:
I looked at a much simpler case of using
input mynum
theninput mybuff[mynum]
instead of the more complicated, nested caseinput mybuff[input mynum]]
.The generated Java compiled:
[...]Trying to simplify it one more layer, and just using
input mybuff[1]
generated Java using the more directmyframeFrame.getMybuffArray0()
instead of the (mynum).subscript() method, so that didn't help.The generated code from
input mybuff[input mynum]
becomes:[...]
I'm wondering why the inner
input mynum]
did not result inmyframeFrame.getMynum()
like it did when it was on its own line. Instead it becamemyframeFrame.widgetMynum()
which was passed as a parameter to themyframeFrame.getMynum()
method. That method doesn't take a parameter.The correct code should be
myframeFrame.getMybuffArray(((myframeFrame.getMynum()).subscript()))
shouldn't it? It compiles, in any case.
I went to a basic input mybuff[x]
where x was just an integer. It generated:
if (_isEqual(myframeFrame.getMybuffArray((x).subscript()), ""))
#14 Updated by Roger Borrello over 4 years ago
What is dynamicindex
annotation used for? I'm trying to determine why the LBRACKET subtree is duplicated in input_builtin_prep.rules
#15 Updated by Roger Borrello over 4 years ago
Roger Borrello wrote:
What is
dynamicindex
annotation used for? I'm trying to determine why the LBRACKET subtree is duplicated ininput_builtin_prep.rules
Still not understanding why the AST has duplicate LBRACKET node created as a child of FUNC_POLY(input). And if that is correct, why isn't there another created, since we have a 2nd input in an LBRACKET?
#16 Updated by Constantin Asofiei over 4 years ago
Roger Borrello wrote:
I went to a basic
input mybuff[x]
where x was just an integer. It generated:
I don't think the subscript
needs to be generated here. This is required in cases like xVar[idx]
, to emit as subscript(xVar, idx)
. In your case, the widget is already emitted correctly, so the subscript
doesn't need to be emitted.
#17 Updated by Constantin Asofiei over 4 years ago
Constantin Asofiei wrote:
Roger Borrello wrote:
I went to a basic
input mybuff[x]
where x was just an integer. It generated:I don't think the
subscript
needs to be generated here. This is required in cases likexVar[idx]
, to emit assubscript(xVar, idx)
. In your case, the widget is already emitted correctly, so thesubscript
doesn't need to be emitted.
I take this back, the subscript
is required to make the index 0-based instead of 1-based, as the frame widgets for an extent var will be numbered 0-based, not 1-based, during conversion.
#18 Updated by Roger Borrello over 4 years ago
Thanks for looking. I had a much more complicated testcase originally, which has been greatly reduced:
define variable mybuff as character extent 1 no-undo. define variable mynum as integer no-undo. define variable x as integer no-undo. form mybuff[1] mynum with frame myframe. do with frame myframe: update mybuff[1] mynum editing: readkey. if input mybuff[input mynum] = "" then message "Blank". else message "Not blank". end. end.
Greg had me add pre and post processing to annotations/input_builtin_prep.rules
to push the id of the kw_input
node so it could be used to access the original node's methodtext
and override
annotations, and add them into the current node.
That allowed us to complete parsing, but the generated Java doesn't compile, as noted above. I am having trouble understanding of the problems is in annotations, or convert.
#19 Updated by Constantin Asofiei over 4 years ago
There's something else going on. This case parses/converts properly:
def var c as int extent 5. def var i as int. form c i with frame f1. def var ch as char. ch = input c[input i]. ch = input c[i]. if input c[input i] = "" then message "1". if input c[i] = "" then message "1".
but if you change the type of c
var to character
, it no longer converts. The conversion was with 3809e.
#20 Updated by Constantin Asofiei over 4 years ago
Roger Borrello wrote:
Thanks for looking. I had a much more complicated testcase originally, which has been greatly reduced:
Same with this test: if you change mybuff
to integer, it will parse and convert properly with 3809e. So, we might have a problem with some special processing for character
widgets.
#21 Updated by Roger Borrello over 4 years ago
Constantin Asofiei wrote:
Roger Borrello wrote:
Thanks for looking. I had a much more complicated testcase originally, which has been greatly reduced:
Same with this test: if you change
mybuff
to integer, it will parse and convert properly with 3809e. So, we might have a problem with some special processing forcharacter
widgets.
If you put both cases in the same testcase (one with character, one with integer) they both have an issue:
define variable mybuff as character extent 1 no-undo. define variable mynums as integer extent 1 no-undo. define variable mynum as integer no-undo. define variable x as integer no-undo. form mybuff[1] mynum with frame f1. form mynums[1] mynum with frame f2. do with frame f1: update mybuff[1] mynum editing: readkey. if input mybuff[input mynum] = "" then message "Blank". else message "Not blank". end. end. do with frame f2: update mynums[1] mynum editing: readkey. if input mynums[input mynum] = 0 then message "Zero". else message "Not zero". end. end.
Converted:
doBlock("blockLabel0", new Block((Body) () -> { FrameElement[] elementList0 = new FrameElement[] { new Element(subscript(mybuff, 1), f1Frame.widgetMybuffArray0()), new Element(mynum, f1Frame.widgetMynum()) }; updateEditing(f1Frame, elementList0, "editingLabel0", new Block((Body) () -> { KeyReader.readKey(); if (_isEqual(f1Frame.getMybuffArray((f2Frame.getMynum(f2Frame.widgetMynum())).subscript()), "")) { message("Blank"); } else { message("Not blank"); } })); })); doBlock("blockLabel1", new Block((Body) () -> { FrameElement[] elementList1 = new FrameElement[] { new Element(subscript(mynums, 1), f2Frame.widgetMynumsArray0()), new Element(mynum, f2Frame.widgetMynum()) }; updateEditing(f2Frame, elementList1, "editingLabel1", new Block((Body) () -> { KeyReader.readKey(); if (_isEqual(f2Frame.getMynumsArray((f2Frame.getMynum(f2Frame.widgetMynum())).subscript()), 0)) { message("Zero"); } else { message("Not zero"); } })); }));
#22 Updated by Roger Borrello over 4 years ago
I see that getScreenValue() is the method used in your testcase. The AST and Java look so much cleaner than in my testcase. How could VAR_CHAR be so much different?
I am on holiday until 31 December. If there's any notes you could leave me, with hints about what to look for, I would be very happy to squash this bug.
#23 Updated by Constantin Asofiei over 4 years ago
Roger, I think I found the root cause. Try replacing the walk-rules
with ascent-rules
in input_builtin_prep.rules
. Why will this work: we have a nested INPUT
function case. But, in case of character
widgets, we do some processing to avoid the getScreenValue()
. This includes duplicating an AST, and marking the original one as hidden. If we do this in the walk-rules, when we duplicate the AST, we duplicate the unprocessed nested INPUT AST. So, doing this on the ascent, we ensure we are duplicating the fully-processed AST.
What made it tick for me was that the nested INPUT AST (inside the hidden AST) had annotations (like methodtxt
), while the copy did not.
#24 Updated by Roger Borrello over 4 years ago
Constantin Asofiei wrote:
Roger, I think I found the root cause. Try replacing the
walk-rules
withascent-rules
ininput_builtin_prep.rules
. Why will this work: we have a nestedINPUT
function case. But, in case ofcharacter
widgets, we do some processing to avoid thegetScreenValue()
. This includes duplicating an AST, and marking the original one as hidden. If we do this in the walk-rules, when we duplicate the AST, we duplicate the unprocessed nested INPUT AST. So, doing this on the ascent, we ensure we are duplicating the fully-processed AST.What made it tick for me was that the nested INPUT AST (inside the hidden AST) had annotations (like
methodtxt
), while the copy did not.
Well Happy New Year! That did the trick for my testcase!
define variable mybuff as character extent 1 no-undo. define variable mynums as integer extent 1 no-undo. define variable mynum as integer no-undo. define variable x as integer no-undo. form mybuff[1] mynum with frame f1. form mynums[1] mynum with frame f2. do with frame f1: update mybuff[1] mynum editing: readkey. if input mybuff[input mynum] = "" then message "Blank". else message "Not blank". end. end. do with frame f2: update mynums[1] mynum editing: readkey. if input mynums[input mynum] = 0 then message "Zero". else message "Not zero". end. end.
Converts to:
package com.goldencode.testcases.input; import com.goldencode.p2j.util.*; import com.goldencode.testcases.ui.input.*; import com.goldencode.p2j.ui.*; import static com.goldencode.p2j.util.BlockManager.*; import static com.goldencode.p2j.util.CompareOps.*; import static com.goldencode.p2j.util.ArrayAssigner.*; import static com.goldencode.p2j.ui.LogicalTerminal.*; /** * Business logic (converted to Java from the 4GL source code * in input/extent_subscript_using_input.p). */ public class ExtentSubscriptUsingInput { ExtentSubscriptUsingInputF1 f1Frame = GenericFrame.createFrame(ExtentSubscriptUsingInputF1.class, "f1"); ExtentSubscriptUsingInputF2 f2Frame = GenericFrame.createFrame(ExtentSubscriptUsingInputF2.class, "f2"); /** * External procedure (converted to Java from the 4GL source code * in input/extent_subscript_using_input.p). */ public void execute() { character[] mybuff = TypeFactory.characterExtent(1); integer[] mynums = TypeFactory.integerExtent(1); integer mynum = TypeFactory.integer(); externalProcedure(ExtentSubscriptUsingInput.this, new Block((Body) () -> { f1Frame.openScope(); f2Frame.openScope(); doBlock("blockLabel0", new Block((Body) () -> { FrameElement[] elementList0 = new FrameElement[] { new Element(subscript(mybuff, 1), f1Frame.widgetMybuffArray0()), new Element(mynum, f1Frame.widgetMynum()) }; updateEditing(f1Frame, elementList0, "editingLabel0", new Block((Body) () -> { KeyReader.readKey(); if (_isEqual(f1Frame.getMybuffArray((f2Frame.getMynum()).subscript()), "")) { message("Blank"); } else { message("Not blank"); } })); })); doBlock("blockLabel1", new Block((Body) () -> { FrameElement[] elementList1 = new FrameElement[] { new Element(subscript(mynums, 1), f2Frame.widgetMynumsArray0()), new Element(mynum, f2Frame.widgetMynum()) }; updateEditing(f2Frame, elementList1, "editingLabel1", new Block((Body) () -> { KeyReader.readKey(); if (_isEqual(f2Frame.getMynumsArray((f2Frame.getMynum()).subscript()), 0)) { message("Zero"); } else { message("Not zero"); } })); })); })); } }
I will look at customer code, too.
#25 Updated by Roger Borrello over 4 years ago
Committed rules/annotations/input_builtin_prep.rules
to 4207a-11367.
#26 Updated by Greg Shah over 4 years ago
- Status changed from WIP to Test
#27 Updated by Roger Borrello about 4 years ago
Task branch 4207a was merged to trunk as revision 11344.
#28 Updated by Greg Shah about 4 years ago
- Status changed from Test to Closed