Page 1 of 1
DO/CASE limits?
Posted: Mon Feb 27, 2023 8:51 pm
by stefan.ungemach
Is there a known limit to the number of CASEs in a DO/CASE construct? I have a simple construct like
DO CASE
CASE symField == #A4HHST
symClass := #HHST
(...)
ENDCASE
where the compiler crashes if I have more than 668 CASE conditions (reproducable). Since this is a strange number I'm not sure about some violated boundaries. Is there a known limit, and is there possibly a better way to deal with the need of processing several thousand of these translations?
DO/CASE limits?
Posted: Mon Feb 27, 2023 9:13 pm
by Chris
Hi Stefan,
There is (was) no such known limit, but I just managed to reproduce the problem here, although in my case I needed to use 1500 case conditions!
This is a compiler bug, but of course indeed this is not the most efficient thing to do this. If all your CASE statements are like those in your code snippet, I would use a hastable/dictionary, which would make the code perform extremely fast and make it more readable I think. Something like:
Code: Select all
USING System.Collections.Generic
FUNCTION CreateTable() AS Dictionary<SYMBOL,SYMBOL>
LOCAL oTable AS Dictionary<SYMBOL,SYMBOL>
oTable := Dictionary<SYMBOL,SYMBOL>{1000}
oTable:Add(#A4HHST, #HHST)
oTable:Add(#ANOTHER, #RESULT)
oTable:Add(#FOO, #BAR)
// ....
RETURN oTable
FUNCTION GetClassFromField(symField AS SYMBOL) AS SYMBOL
STATIC LOCAL oTable := CreateTable() AS Dictionary<SYMBOL,SYMBOL>
IF oTable:ContainsKey(symField)
RETURN oTable[symField]
END IF
RETURN null_SYMBOL
FUNCTION Start() AS VOID
LOCAL symField,symClass AS SYMBOL
symField := #A4HHST
symClass := GetClassFromField(symField)
? symClass
symField := #FOO
symClass := GetClassFromField(symField)
? symClass
Just make sure that the hashtable is created only once! (hence the STATIC local in my sample).
Another option would be to use SWITCH instead of DO CASE, but I think the hashtable is a more elegant solution.
DO/CASE limits?
Posted: Mon Feb 27, 2023 9:45 pm
by stefan.ungemach
Thank you Chris,
the hashtable is a much smarter solution - especially because we're talking of generated code here which leads to several thousand elements. I have several use cases for this
DO/CASE limits?
Posted: Mon Feb 27, 2023 10:02 pm
by Chris
You're welcome!
Just for completeness, using a SWITCH instead of a DO CASE, will also generate code that internally uses a hash table, so it will also be very fast. But not so readable/elegant, when you have so many cases.
DO/CASE limits?
Posted: Tue Feb 28, 2023 7:07 am
by robert
Chris,
Chris post=25416 userid=313 wrote:Hi Stefan,
There is (was) no such known limit, but I just managed to reproduce the problem here, although in my case I needed to use 1500 case conditions!
Do you convert your test code into a Github issue?
And maybe I should fix it by displaying an error message about "bad code quality"?
Robert
DO/CASE limits?
Posted: Tue Feb 28, 2023 7:09 am
by leon-ts
Hi guys,
I would also suggest using the TryGetValue method in this particular case to immediately check and get the value if it is in the dictionary:
Code: Select all
IF oTable:TryGetValue(symField, OUT symFoundClass AS SYMBOL)
RETURN symFoundClass
END IF
Best regards,
Leonid
DO/CASE limits?
Posted: Tue Feb 28, 2023 7:44 am
by Chris
Robert, done!
Leonid, good point!
And note to myself, a SWITCH command does not allow a SYMBOL for its expression
.
DO/CASE limits?
Posted: Tue Feb 28, 2023 10:11 am
by stefan.ungemach
Thanks again to all. I have chosen Leonid's approach.
DO/CASE limits?
Posted: Tue Feb 28, 2023 11:15 am
by robert
Chris,
Chris post=25421 userid=313 wrote:Robert, done!
And note to myself, a SWITCH command does not allow a SYMBOL for its expression
.
In that case use Symbol2String() on the symbol and compare with (uppercase) literal strings,.
The compiler will compare hashcodes, so that is relatively fast.
Robert