Bug #4484
Accumulator confusion using same field for count and total
100%
History
#2 Updated by Roger Borrello over 6 years ago
Testcase¶
20191231 Update: Fixed in 4207a-11366
Checked in: uast/accum_overlap_count-total.p
define temp-table tt
field f1 as character format "x(8)"
field f2 as decimal format "->>>>>9.99".
create tt. tt.f1 = "1". tt.f2 = 0.
create tt. tt.f1 = "2". tt.f2 = 0.
for each tt
break by f1:
accumulate tt.f2 (count by f1).
accumulate tt.f2 (total by f1).
end.
message "Done.".
Output from java compiler¶
[javac] testcases/uast/uast/buildarea/src/com/goldencode/testcases/abl/AccumOverlapCountTotal.java:27: error: cannot find symbol
[javac] final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
[javac] ^
[javac] symbol: variable fieldRef0
[javac] location: class AccumOverlapCountTotal
java emitted¶
public void execute()
{
final CountAccumulator accumCount0 = new CountAccumulator();
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
externalProcedure(AccumOverlapCountTotal.this, new Block((Body) () ->
Just to show what happens when you introduce a new field f3 to receive the total accumulator:
public void execute()
{
final CountAccumulator accumCount0 = new CountAccumulator();
FieldReference fieldRef1 = new FieldReference(tt, "f3");
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef1);
externalProcedure(AccumOverlapCountTotal.this, new Block((Body) () ->
#3 Updated by Constantin Asofiei over 6 years ago
This might be related to COUNT which doesn't necessarily need the field reference; so, please expand your test to replace the COUNT accumulator with something else, and see if fieldRef is still emitted.
My assumption is that there is some rule somewhere in TRPL, which says 'do not emit the expression for a COUNT accumulator', but it doesn't track if this expression (i.e. field) is used in some other accumulator.
#4 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
This might be related to
COUNTwhich doesn't necessarily need the field reference; so, please expand your test to replace the COUNT accumulator with something else, and see if fieldRef is still emitted.My assumption is that there is some rule somewhere in TRPL, which says 'do not emit the expression for a COUNT accumulator', but it doesn't track if this expression (i.e. field) is used in some other accumulator.
I updated the testcase to use AVERAGE and it didn't mind at all!
define temp-table tt
field f1 as character format "x(8)"
field f2 as decimal format "->>>>>9.99".
create tt. tt.f1 = "1". tt.f2 = 0.
create tt. tt.f1 = "2". tt.f2 = 0.
for each tt
break by f1:
accumulate tt.f2 (average by f1).
accumulate tt.f2 (total by f1).
end.
message "Done.".
This emitted:
public void execute()
{
FieldReference fieldRef0 = new FieldReference(tt, "f2");
final AverageAccumulator accumAvg0 = new AverageAccumulator(fieldRef0);
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
externalProcedure(AccumOverlapCountTotal.this, new Block((Body) () ->
{
RecordBuffer.openScope(tt);
tt.create();
tt.setF1(new character("1"));
tt.setF2(new integer(0));
tt.create();
tt.setF1(new character("2"));
tt.setF2(new integer(0));
PresortQuery query0 = new PresortQuery();
FieldReference byExpr0 = new FieldReference(tt, "f1");
forEach("loopLabel0", new Block((Init) () ->
{
query0.initialize(tt, ((String) null), null, "tt.id asc");
query0.enableBreakGroups();
query0.setNonScrolling();
query0.addSortCriterion(byExpr0);
query0.addAccumulator(accumAvg0);
accumAvg0.addBreakGroup(byExpr0);
accumAvg0.reset();
query0.addAccumulator(accumTotal0);
accumTotal0.addBreakGroup(byExpr0);
accumTotal0.reset();
},
(Body) () ->
{
query0.next();
accumAvg0.accumulate();
accumTotal0.accumulate();
}));
message("Done.");
}));
}
}
#5 Updated by Constantin Asofiei over 6 years ago
OK, I think this confirms the problem is with COUNT. Look at process_aggregate function in annotations/accumulate.rules, there might be a problem there; and the referenced annotation in the AST.
#6 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
OK, I think this confirms the problem is with COUNT. Look at
process_aggregatefunction inannotations/accumulate.rules, there might be a problem there; and thereferencedannotation in the AST.
Just to further that theory, as I start to look at the rules... as long as COUNT is not first, we are good:
accumulate tt.f2 (total by f1).
accumulate tt.f2 (count by f1).
accumulate tt.f2 (average by f1).
FieldReference fieldRef0 = new FieldReference(tt, "f2");
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
final CountAccumulator accumCount0 = new CountAccumulator();
final AverageAccumulator accumAvg0 = new AverageAccumulator(fieldRef0);
accumulate tt.f2 (average by f1).
accumulate tt.f2 (count by f1).
accumulate tt.f2 (total by f1).
FieldReference fieldRef0 = new FieldReference(tt, "f2");
final AverageAccumulator accumAvg0 = new AverageAccumulator(fieldRef0);
final CountAccumulator accumCount0 = new CountAccumulator();
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
Both emit compilable code. Put COUNT first...
accumulate tt.f2 (count by f1).
accumulate tt.f2 (average by f1).
accumulate tt.f2 (total by f1).
final CountAccumulator accumCount0 = new CountAccumulator();
final AverageAccumulator accumAvg0 = new AverageAccumulator(fieldRef0);
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
The process_aggregate function certainaly seems to be the place to focus, but I'm not sure if the fix would just be to annotate for COUNT as well.
<!-- annotate the expression to indicate it is being referenced by
an ACCUMULATE statement; we DO NOT make this annotation if
the aggregation type is COUNT, because this type does not
actually use the expression, so it will not be necessary to
emit the expression if it is only referenced by COUNT types -->
<expression>
expr.getAncestor(-1, prog.expression).putAnnotation("referenced", referenced)
</expression>
#7 Updated by Roger Borrello over 6 years ago
This looks like the culprit...
<!-- an ACCUMULATE statement expression initially is considered referenced if either it
already has been marked as referenced by a sibling AGGREGATE child node, or if it
is not used within a count or sub-count accumulation; this may be overridden below
if we determine an accumulator object already is defined in the same scope with
the same expression -->
<expression>
referenced = (exprRef.isAnnotation("referenced") and
(#(boolean) exprRef.getAnnotation("referenced"))) or
(type != prog.kw_count and type != prog.kw_sub_cnt)
</expression>
Would it be simple as removing the check for prog.kw_count? It would seem we'd just create a reference when it may not be needed.
#8 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
This looks like the culprit...
[...]
Would it be simple as removing the check for
prog.kw_count? It would seem we'd just create a reference when it may not be needed.
It wasn't that simple, because it no longer created a reference to the field when I removed the or (type != prog.kw_count and type != prog.kw_sub_cnt) as all the other cases no longer fulfilled the criteria. Just setting referenced = true works, but I definitely need more information on the requirements for process_aggregate.
#9 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
The only place where the private functionRoger Borrello wrote:
This looks like the culprit...
[...]
Would it be simple as removing the check for
prog.kw_count? It would seem we'd just create a reference when it may not be needed.It wasn't that simple, because it no longer created a reference to the field when I removed the
or (type != prog.kw_count and type != prog.kw_sub_cnt)as all the other cases no longer fulfilled the criteria. Just settingreferenced = trueworks, but I definitely need more information on the requirements forprocess_aggregate.
process_aggregate is called is when we are processing:
- type prog.kw_count or type prog.kw_sub_cnt
- type prog.kw_average or type prog.kw_sub_avg
- type prog.kw_max or type prog.kw_sub_max
- type prog.kw_min or type prog.kw_sub_min
- type prog.kw_total or type prog.kw_sub_tot
I believe it is safe to add the reference in all those circumstances. The override to false is done if the name has already been referenced.
#10 Updated by Roger Borrello over 6 years ago
Doing some research related to what makes these aggregate functions order-dependent.
Run 1
accumulate tt.f2 (count by f1).
accumulate tt.f2 (average by f1).
accumulate tt.f2 (total by f1).
Run 2
accumulate tt.f2 (average by f1).
accumulate tt.f2 (count by f1).
accumulate tt.f2 (total by f1).
There was no difference between the AST STATEMENT/KW_ACCUM/EXPRESSION AGGREGATE/KW_TOTAL section for run 1 and 2. Understandable, since nothing changed in relation to the runs.
STATEMENT/KW_ACCUM/EXPRESSION AGGREGATE/KW_COUNT, where count was in the 1st position on run 1, and 2nd position on run 2:
STATEMENT/KW_ACCUM/EXPRESSIONhas a peerid annotation, which doesn't appear in that section of when it was in the 2nd position.
STATEMENT/KW_ACCUM/EXPRESSION AGGREGATE/KW_AVERAGE, where average was in the 2nd position on run 1, and 1st position on run 2:
STATEMENT/KW_ACCUM/EXPRESSION/FIELD_DEChas a peerid annotation on the 2nd run, when it was in the 1st position.
Interesting that there is a peerid annotation for each when it was in the 1st position, but for count, it was on the EXPRESSION node, but for average it was on the field.
Regarding the EXPRESSION annotations, they were as expected. Regardless of the position of the accumulator, count had referenced=false for javaname=fieldRef0 whether it was first or second, while average had referenced=true for javaname=fieldRef0 whether it was first or second.
So the main difference seems to be where the peerid annotation is attached.
#11 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
Doing some research related to what makes these aggregate functions order-dependent.
Run 1
[...]Run 2
[...]There was no difference between the AST
Comparing run 1 to run 2 of the ASTSTATEMENT/KW_ACCUM/EXPRESSION AGGREGATE/KW_TOTALsection for run 1 and 2. Understandable, since nothing changed in relation to the runs.STATEMENT/KW_ACCUM/EXPRESSION AGGREGATE/KW_COUNT, where count was in the 1st position on run 1, and 2nd position on run 2:Comparing run 1 to run 2 of the AST
STATEMENT/KW_ACCUM/EXPRESSIONhas a peerid annotation, which doesn't appear in that section of when it was in the 2nd position.STATEMENT/KW_ACCUM/EXPRESSION AGGREGATE/KW_AVERAGE, where average was in the 2nd position on run 1, and 1st position on run 2:
STATEMENT/KW_ACCUM/EXPRESSION/FIELD_DEChas a peerid annotation on the 2nd run, when it was in the 1st position.Interesting that there is a peerid annotation for each when it was in the 1st position, but for count, it was on the
EXPRESSIONnode, but for average it was on the field.Regarding the
EXPRESSIONannotations, they were as expected. Regardless of the position of the accumulator, count had referenced=false for javaname=fieldRef0 whether it was first or second, while average had referenced=true for javaname=fieldRef0 whether it was first or second.So the main difference seems to be where the peerid annotation is attached.
OK... so that was a red herring (thanks, Greg, for keeping out of that rabbit hole). However, in looking at the actions of convert/database_references.rules it looks like this line is preventing a constructor for the FieldReference from being emitted:
<!-- a field reference child of an ACCUMULATE statement expression that is not
referenced (for example, a count or sub-count aggregate or an expression
that is identical to an accumulator already constructed in the same
scope) should not be emitted -->
<rule>this.getAncestor(-1, prog.expression, "referenced", false) != null
<action>printfln("database_reference.walk_rules: We are being suppressed! javaname=%s", javaname)</action>
<action>suppress = true</action>
</rule>
Where can I learn more about getAncestor? It may need to be smarter about whether there are any other nodes that need to reference it.
#12 Updated by Constantin Asofiei over 6 years ago
Roger, is this limited only for fields? Does FWD convert OK if you replace the field with some variable?
#13 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Roger, is this limited only for fields? Does FWD convert OK if you replace the field with some variable?
Is that even possible? How could you aggregate a variable? Would it be an extent?
#14 Updated by Constantin Asofiei over 6 years ago
This works fine in 4GL:
def var i as int.
repeat i = 1 to 10:
accumulate i (average).
accumulate i (total).
end.
#15 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
This works fine in 4GL:
[...]
I added count...
def var i as int.
repeat i = 1 to 10:
accumulate i (count).
accumulate i (average).
accumulate i (total).
end.
message "Done.".
It converts/compiles fine. The variable is defined, versus the field reference using a database.
public class Doit
{
integer i = UndoableFactory.integer();
/**
* External procedure (converted to Java from the 4GL source code
* in abl/doit.p).
*/
public void execute()
{
final CountAccumulator accumCount0 = new CountAccumulator();
final AverageAccumulator accumAvg0 = new AverageAccumulator(i);
final TotalAccumulator accumTotal0 = new TotalAccumulator(i);
externalProcedure(Doit.this, new Block((Body) () ->
{
ToClause toClause0 = new ToClause(i, 1, 10);
repeatTo("loopLabel0", toClause0, new Block((Init) () ->
{
accumCount0.reset();
accumAvg0.reset();
accumTotal0.reset();
},
(Body) () ->
{
accumCount0.accumulate();
accumAvg0.accumulate();
accumTotal0.accumulate();
}));
message("Done.");
}));
}
}
The scope of the variable is very difference from field reference in the database version:
public void execute()
{
FieldReference fieldRef0 = new FieldReference(tt, "f2");
final AverageAccumulator accumAvg0 = new AverageAccumulator(fieldRef0);
final CountAccumulator accumCount0 = new CountAccumulator();
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
#16 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
Constantin Asofiei wrote:
This works fine in 4GL:
[...]I added count...
[...]It converts/compiles fine. The variable is defined, versus the field reference using a database.
[...]
The scope of the variable is very difference from field reference in the database version:
[...]
Interesting... if we have nothing but count, it still declares i:
public class Doit
{
integer i = UndoableFactory.integer();
/**
* External procedure (converted to Java from the 4GL source code
* in abl/doit.p).
*/
public void execute()
{
final CountAccumulator accumCount0 = new CountAccumulator();
externalProcedure(Doit.this, new Block((Body) () ->
{
ToClause toClause0 = new ToClause(i, 1, 10);
// accumulate i (average).
repeatTo("loopLabel0", toClause0, new Block((Init) () ->
{
accumCount0.reset();
},
(Body) () ->
{
accumCount0.accumulate();
}));
// accumulate i (total).
message("Done.");
}));
}
}
#17 Updated by Constantin Asofiei over 6 years ago
OK, try this, too:
def var i as int.
repeat i = 1 to 10:
accumulate i + 1 (count).
accumulate i + 1 (average).
accumulate i + 1 (total).
end.
Is normal to declare i, as is an explicit var. I'm trying to understand if this is an issue limited to fields or any kind of accumulator expression.
#18 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
OK, try this, too:
[...]Is normal to declare
i, as is an explicit var. I'm trying to understand if this is an issue limited to fields or any kind of accumulator expression.
I tried that immediately above. It is an issue limited to fields. Are we trying to be too fine and only construct a field reference for non count/subcount? I will look into this. Is it generally known the expense of instantiating a field reference it too big a price to take for all the customers that are using count accumulators on fields? We seem to be taking it for variables.
#19 Updated by Constantin Asofiei over 6 years ago
Roger Borrello wrote:
I tried that immediately above. It is an issue limited to fields. Are we trying to be too fine and only construct a field reference for non count/subcount? I will look into this. Is it generally known the expense of instantiating a field reference it too big a price to take for all the customers that are using count accumulators on fields? We seem to be taking it for variables.
With variables, is normal and required to exist only one definition. For fields, we need to use a FieldReference because we can't use the getter (as in tt1.getF1()) - the getter gives us the 'current value', while the accumulator needs to be allowed to resolve the value each time it needs it (i.e. FieldReference is a Resolvable).
The idea behind emitting only one FieldReference, and use that for any accumulator which matches it, was an optimization.
#20 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Roger Borrello wrote:
I tried that immediately above. It is an issue limited to fields. Are we trying to be too fine and only construct a field reference for non count/subcount? I will look into this. Is it generally known the expense of instantiating a field reference it too big a price to take for all the customers that are using count accumulators on fields? We seem to be taking it for variables.
With variables, is normal and required to exist only one definition. For fields, we need to use a
FieldReferencebecause we can't use the getter (as intt1.getF1()) - the getter gives us the 'current value', while the accumulator needs to be allowed to resolve the value each time it needs it (i.e. FieldReference is a Resolvable).The idea behind emitting only one FieldReference, and use that for any accumulator which matches it, was an optimization.
Not a good idea to undo any of that. So we should consider this unique to fields. So I'll go back to learning about getAncestor().
#21 Updated by Constantin Asofiei over 6 years ago
Roger, there's another different in the AST: look for the hidden attribute at the AST node; this depends on the suppress value in annotations/accumulate.rules. I don't think the problem is with getAncestor, but with the fact that the ASTs are hidden.
#22 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Roger, there's another different in the AST: look for the
hiddenattribute at the AST node; this depends on thesuppressvalue inannotations/accumulate.rules. I don't think the problem is withgetAncestor, but with the fact that the ASTs are hidden.
I'll investigate. Thank you.
#23 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
Constantin Asofiei wrote:
Roger, there's another different in the AST: look for the
hiddenattribute at the AST node; this depends on thesuppressvalue inannotations/accumulate.rules. I don't think the problem is withgetAncestor, but with the fact that the ASTs are hidden.I'll investigate. Thank you.
I gave it some investigation...
| Node | AVG First | CNT First |
|---|---|---|
| STATEMENT/KW_ACCUM/EXPRESSION | Hidden not set | Hidden not set |
| STATEMENT/KW_ACCUM/EXPRESSION | referenced=true | referenced=false |
Since there isn't any difference between hidden settings, how could it help? We need to be able to go back to the parent BLOCK, then see if any STATEMENT/KW_ACCUM/EXPRESSION have referenced=true. If so, either they should all have it, or at least the first child should.
#24 Updated by Constantin Asofiei over 6 years ago
KW_ACCUM/EXPRESSION nodes. Once COUNT is encountered, any STATEMENT/KW_ACCUM/EXPRESSION will have hidden="true". So:
- if COUNT is first, the expression is not emitted as all subsequent expressions are hidden, too.
- if COUNT is not first, then at least one case will not be hidden, and the expression will be emitted.
#25 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Check the otherI see what you are saying, but wouldn't we need anKW_ACCUM/EXPRESSIONnodes. Once COUNT is encountered, anySTATEMENT/KW_ACCUM/EXPRESSIONwill havehidden="true". So:
- if COUNT is first, the expression is not emitted as all subsequent expressions are hidden, too.
- if COUNT is not first, then at least one case will not be hidden, and the expression will be emitted.
annotations/accumulate_post.rules to:
- Stop at
BLOCK/STATEMENT/KW_ACCUM - Find first
KW_ACCUM/AGGREGATEchild - If first child is
prog.kw_countorprog.kw_sub_cnt- Find all
KW_ACCUM/AGGREGATEchildren with exprname =KW_ACCUM/EXPRESSION(javaname) - Set
KW_ACCUM/EXPRESSION(referenced = true)
- Find all
#26 Updated by Constantin Asofiei over 6 years ago
Roger, please check this patch:
### Eclipse Workspace Patch 1.0
#P p2j
Index: rules/annotations/accumulate.rules
===================================================================
--- rules/annotations/accumulate.rules (revision 2213)
+++ rules/annotations/accumulate.rules (working copy)
@@ -428,13 +428,13 @@
aggregate types are count or sub-count -->
<rule on="false">evalLib("fieldtype", ref.type)
<rule>javaname == null
- <action>suppress = true</action>
+ <action>suppress = false</action>
<action>aggref = this.nextSibling</action>
<rule>aggref != null
<action>childref = aggref.firstChild</action>
<while>childref != null
- <rule>childref.type != prog.kw_count and type != prog.kw_sub_cnt
- <action>suppress = false</action>
+ <rule>childref.type == prog.kw_count or type == prog.kw_sub_cnt
+ <action>suppress = true</action>
<break/>
<action on="false">childref = childref.nextSibling</action>
</rule>
The problem was that the check if the expression needs to be suppressed or not was incorrect: it needs to look if there are COUNT or SUB-COUNT nodes. Instead, it was looking if there is at least a node which is not COUNT or SUB-COUNT - as it was finding the BY clause, it was emitting a javaname for this expression, which messed up the exprNames dictionary, and which lead to the incorrect assumption 'there is a javaname for this expression, then it means it was already emitted, so hide the AST' (see <action on="false">copy.setHidden(true)</action> on line 448).
#27 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Roger, please check this patch:
[...]The problem was that the check if the expression needs to be suppressed or not was incorrect: it needs to look if there are COUNT or SUB-COUNT nodes. Instead, it was looking if there is at least a node which is not COUNT or SUB-COUNT - as it was finding the
BYclause, it was emitting ajavanamefor this expression, which messed up theexprNamesdictionary, and which lead to the incorrect assumption 'there is a javaname for this expression, then it means it was already emitted, so hide the AST' (see<action on="false">copy.setHidden(true)</action>on line 448).
Yes! That will be my early Christmas present!
final CountAccumulator accumCount0 = new CountAccumulator();
FieldReference fieldRef0 = new FieldReference(tt, "f2");
final AverageAccumulator accumAvg0 = new AverageAccumulator(fieldRef0);
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
#28 Updated by Roger Borrello over 6 years ago
Update to rules/annotations/accumulate.rules checked into 4207a-11358.
#29 Updated by Roger Borrello over 6 years ago
- Status changed from New to WIP
#30 Updated by Roger Borrello over 6 years ago
Found a subsequent error, when multiple accumulators are on the same statement.
Added a new testcase uast/accum_single_line_count-total.p
There are many permutations possible, but as long as COUNT is in the mix, there will be a missing FieldReference.
#31 Updated by Constantin Asofiei over 6 years ago
Roger, see 4207a rev 11362, it should fix the issue.
#32 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Roger, see 4207a rev 11362, it should fix the issue.
I'll take a look
#33 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
Constantin Asofiei wrote:
Roger, see 4207a rev 11362, it should fix the issue.
I'll take a look
There's a typo in there, as <action>supress = false</action should be <action>suppress = false</action
I will fix that. :-)
#34 Updated by Roger Borrello over 6 years ago
Just reporting that there is another scenario which creates a hidden FieldRef. I checked in uast/accum/accum_count_hiding_fieldref.p
define temp-table tt
field f1 as character format "x(8)"
field f2 as decimal format "->>>>>9.99"
field f3 as integer.
create tt. tt.f1 = "1". tt.f2 = 0. tt.f3 = 1.
create tt. tt.f1 = "2". tt.f2 = 0. tt.f3 = 1.
/* As long as COUNT is first, it will break */
for each tt
break by f1:
accumulate tt.f2 (count by f1).
accumulate tt.f2 (total by f1).
accumulate tt.f3 (total by f1).
end.
message "Done.".
This results in
final CountAccumulator accumCount0 = new CountAccumulator();
final TotalAccumulator accumTotal0 = new TotalAccumulator(fieldRef0);
FieldReference fieldRef1 = new FieldReference(tt, "f3");
final TotalAccumulator accumTotal1 = new TotalAccumulator(fieldRef1);
#35 Updated by Constantin Asofiei over 6 years ago
Argh, there was another typo. fixed in 11366
#36 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Argh, there was another typo. fixed in 11366
Great... this update worked! We need to take accumulate out back for a good beating! :-)
The affected customer files now compile, too!
#37 Updated by Greg Shah over 6 years ago
- Status changed from WIP to Test
- % Done changed from 0 to 100
#38 Updated by Roger Borrello over 6 years ago
- Status changed from Test to WIP
#39 Updated by Roger Borrello over 6 years ago
The code no longer creates a field reference when there is a [ downpath:
define temp-table tt field f1 as int extent 2.
create tt. tt.f1[1] = 0. tt.f1[2] = 1.
create tt. tt.f1[1] = 0. tt.f1[2] = 1.
for each tt
break by f1:
accumulate tt.f1[1] (count).
accumulate tt.f1[1] (total).
//accumulate tt.f1[2] (total).
end.
message "Done.".
You get
[javac] testcases/src/com/goldencode/testcases/accum/AccumSimple.java:27: error: cannot find symbol
[javac] final TotalAccumulator accumTotal0 = new TotalAccumulator(accumExpr0);
[javac] ^
[javac] symbol: variable accumExpr0
[javac] location: class AccumSimple
[javac] 1 error
#40 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
The code no longer creates a field reference when there is a
[downpath:[...]
You get
[...]
Constantin, what was the testcase you were working with for validating this change to rules/annotations/accumulate.rules:
** CA 20191219 A subscripted field/var in an accumulator must convert as an ** expression.
I remove the and !ref.downPath("LBRACKET") condition, and my new testcase works.
Checked in uast/accum/accum_count_and_total_for_extent_field.p
#41 Updated by Roger Borrello over 6 years ago
Roger Borrello wrote:
Roger Borrello wrote:
The code no longer creates a field reference when there is a
[downpath:[...]
You get
[...]Constantin, what was the testcase you were working with for validating this change to
rules/annotations/accumulate.rules:
[...]I remove the
and !ref.downPath("LBRACKET")condition, and my new testcase works.Checked in
uast/accum/accum_count_and_total_for_extent_field.p
Hi Constantin... fyi my regression testing was successful with that code removed. What was the reason for adding it?
#42 Updated by Constantin Asofiei over 6 years ago
Roger Borrello wrote:
Hi Constantin... fyi my regression testing was successful with that code removed. What was the reason for adding it?
The reason was a miss-understanding of the initial issue... remember the subsequent revisions which further improved your scenarios? This change should not have survived them. So please commit this change and remove my history entry, as is incorrect.
#43 Updated by Roger Borrello over 6 years ago
Constantin Asofiei wrote:
Roger Borrello wrote:
Hi Constantin... fyi my regression testing was successful with that code removed. What was the reason for adding it?
The reason was a miss-understanding of the initial issue... remember the subsequent revisions which further improved your scenarios? This change should not have survived them. So please commit this change and remove my history entry, as is incorrect.
Thank you. Committed to 4207a-11380
#44 Updated by Roger Borrello over 6 years ago
- Assignee set to Roger Borrello
- Status changed from WIP to Review
Task branch 4207a was merged to trunk as revision 11344. Task can be moved to closed. It was still in WIP.
#45 Updated by Greg Shah over 6 years ago
- Status changed from Review to Closed