dao
dao copied to clipboard
Bitwise operations do not work on flag enum literals.
enum MyEnum
{
A;
B;
C;
}
var AB = MyEnum.A + MyEnum.B;
var BC = MyEnum.B + MyEnum.C;
var intersection = AB & BC;
This works correctly - intersection is equal to MyEnum.B.
enum MyEnum
{
A;
B;
C;
}
var intersection = MyEnum.A & MyEnum.C;
>>> [[ERROR]] in file "code string+":
At line 1 : Invalid statement --- " MyEnum ";
At line 1 : Invalid expression --- " MyEnum. A & MyEnum. C; ";
At line 1 : invalid constant expression;
At line 1 : Constant evaluation aborted with exception(s) ---
[[Error::Value]] --- Invalid value:
invalid operands
In code snippet:
>> 0 : DATA : 0 , 0 , 0 ; 0;
Raised by: (), at instruction 0 in line 0 in file "interactive codes";
This doesn't work. I would expect anything that can be done on a variable containing the enum would be possible on a literal of the enum.
&
is not a valid operation on enums, and var intersection = AB & BC;
doesn't work for me (tried in the interactive mode). I don't think intersection have any real meaning and application in the context of enums.
Sorry, but that's another case of "I haven't used it, so no one has."
An intersection on flags means "I have two objects and I want to get the list of flags that applies to both of them." There are use cases for that.
Also, I tried var intersection = AB & BC;
in interactive mode as well, and it worked fine. I'm using the latest code pulled from the git repository.
Just to give a practical example of where flag (or set) intersection is extremely useful:
Suppose I'm writing the game The Sims. Now suppose in my AI routine, I have two Sims who have gotten together and now the routine determines they want to do something together (say, go on a date).
Now each Sim could have a list of things they're interested in. This might be stored as a set, but to save memory (on consoles, saving even a few bytes of memory is still important), they're stored as flags. (And this, by the way, is also an example of a case where more than 32 flags could very well be necessary. The Sims might have a LOT of possible things for a Sim to be interested in.)
So each Sim has a set of flags saying what they're interested in. One of them is interested in ACTIONMOVIES and one is interested in ROMANCEFILMS and one is interested in BASKETBALL, etc. My AI routine now needs to pick something for them to go do together and it should probably be something they're both interested in.
Set of things they're both interested in: SimA.interests & SimB.interests
MUCH more efficient than iterating through each flag and checking if it's in both of them. Orders of magnitude more efficient.
Also, I tried var intersection = AB & BC; in interactive mode as well, and it worked fine. I'm using the latest code pulled from the git repository.
I've tried it with the latest revision from the fossil repo (it's the primary one). Doesn't work.
But you are right, this may come in handy sometimes. Apparently, the operation was meant to be supported anyway.
That's strange. I just went to try it again and now it doesn't work. I wonder what I did to get my console into a state where it was working before.
(dao) enum MyEnum { A; B; C; }
= none
(dao) var AB = MyEnum.A + MyEnum.B
= none
(dao) var BC = MyEnum.B + MyEnum.C
= none
(dao) AB & BC
[[Error::Value]] --- Invalid value:
invalid operands
In code snippet:
1 : GETVG : 0 , 3 , 1 ; 1; BC
>> 2 : BITAND : 0 , 1 , 2 ; 1; AB & BC
3 : RETURN : 2 , 1 , 0 ; 1; AB & BC
Raised by: __main__(), at instruction 2 in line 1 in file "interactive codes";
(dao) AB2 = MyEnum.A + MyEnum.B
= $A$B(3)
(dao) BC2 = MyEnum.B + MyEnum.C
= $B$C(6)
(dao) AB2 & BC2
= $B(2)
Apparently it works if you do not use the var
keyword, but does not work if you do use the var
keyword.
(dao) meta.typeOf(AB)
= type<MyEnum>_21_0x25bd7c0
(dao) meta.typeOf(AB2)
= type<MyEnum>_21_0x25bd7c0
No difference between them that I can see.
I've found some information on what's going on with this one...
In DaoProcess_DoBitLogic()
I'm seeing checks to ensure that the types are the same. What I see is two things:
- When doing this with enum literals,
DaoProcess_GetEnum()
is returningNULL
. In this caseself->activeTypes[0]
, which is what's being accessed to get this type, isNULL
- When doing it with enums declared with the
var
keyword,DaoProcess_GetEnum()
is returning an enum with a different type than the two enums being operated on. Strangely in this case,self->activeTypes[0]
is the same asself->activeTypes[1]
is the same asself->activeTypes[2]
is the same as the value returned, andself->activeValues[0]->xEnum.etype
andself->activeValues[1]->xEnum.etype
are also the same value as each other... but they're not the same value as the values inself->activeTypes
This is the line that throws the error in both cases:
if( en == NULL || en->etype != A->xEnum.etype )
goto InvalidOperation;