I have an enum ValueKind and set based on this: ValueSpec = set[ValueKind]
Most of the times I use something like someValue in someSpec, the test works correctly and transformed into bit arithmetic (in the C code).
I have one particular case I've been struggling with, which I cannot get to work no-matter-what (or at least, I can get it to work up to some point, but not exactly as I want to).
Here's a case: https://github.com/arturo-lang/arturo/blob/master/src/vm/lib.nim#L204 (which is obviously a template)
Being called in this template: https://github.com/arturo-lang/arturo/blob/master/src/vm/lib.nim#L90
And usually used like this: https://github.com/arturo-lang/arturo/blob/master/src/library/Arithmetic.nim#L34-L36
As you can see, the element in question is args which is actually an array of (string,ValueSpec) tuples, mostly processed at compile time - basically, the value is always known at compile time.
So, I would expect the first statement to be processed like a regular in for sets.
What I currently see in the generated C code instead is something like:
T9_ = NIM_UNLIKELY(!(((*x).kind == ((tyEnum_ValueKind__qAQGwFnJ6IiIf72h9c6dBqQ) 2) || (*x).kind == ((tyEnum_ValueKind__qAQGwFnJ6IiIf72h9c6dBqQ) 3) || (*x).kind == ((tyEnum_ValueKind__qAQGwFnJ6IiIf72h9c6dBqQ) 4) || (*x).kind == ((tyEnum_ValueKind__qAQGwFnJ6IiIf72h9c6dBqQ) 5) || (*x).kind == ((tyEnum_ValueKind__qAQGwFnJ6IiIf72h9c6dBqQ) 21) || (*x).kind == ((tyEnum_ValueKind__qAQGwFnJ6IiIf72h9c6dBqQ) 19) || (*x).kind == ((tyEnum_ValueKind__qAQGwFnJ6IiIf72h9c6dBqQ) 11))));
...which looks like an absolute total overkill.
What should be done is check (*x).kind against the OR-ed result of the already-known set.
I guess there must be something off with the templates or the actually code being injected in a proc, but I'm not sure.
Any suggestions?
Well, the so-many uses of static are to be cleaned up. That's exactly what I'm working on right now.
Having said this, the test x.kind in spec[0][0] for example cannot be static in its entirety since x.kind is not known at compile-time. spec[0][0] is, however.
I imagined that. But I'd still like to benchmark the two version to see if there is any actual difference.
At some point (I honestly don't remember how; it was after moving the different parts around and trying to pass just an one-dimensional array to require, I think), I got it to work... but still not absolutely right.
I've asked just in case someone has a clearer idea of what is going on here... :)
Observation (I spotted it!)
If I change this:
if unlikely(not (x.kind in static spec[0][1])):
to this (basically, just remove static):
if unlikely(not (x.kind in spec[0][1])):
then it compiles to:
T9_ = NIM_UNLIKELY(!(((TM__IPU5x6F5i1TFKZ7WkUj8KQ_6[(((NI) 0))- 0].Field1 &((NU64)1<<((NU)((*x).kind)&63U)))!=0)));
which is close, but not quite.
I mean... yeah, if it wasn't known at compile-time, I get this TM__IPU5x6F5i1TFKZ7WkUj8KQ_6[(((NI) 0))- 0].Field1 part - but it's still a simple number...
defined like:
static NIM_CONST tyArray__FA724GdeAsO7h22H9czSIxA TM__IPU5x6F5i1TFKZ7WkUj8KQ_6 = {{{6, (NimStrPayload*)&TM__IPU5x6F5i1TFKZ7WkUj8KQ_7},
2623548}
So... why all this?
Or shouldn't I even bother in this case?
Bad idea: Looking at the C code.
Better idea: Looking at the assembler code.
Even better idea: Looking at the results of a profiler.
Best idea: Stop using LaTeX.