xsharp.eu • DO/CASE limits?
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