Page 1 of 2

Enum has Flags and bitwise operations

PostPosted: Thu Sep 20, 2012 8:33 pm
by nerdzero
Should this work?

"""
Cobra svn:2795 (post 0.8) / 2012-09-11 on Mono 2.10.8.1 CLR v4.0.30319 on Ubuntu 12.04.1 LTS
"""

enum TestEnum
has Flags
None = 0
First = 1
Second = 2
Third = 4
Fourth = 8

class TestProgram

var t as TestEnum = TestEnum.First & TestEnum.Second

def main

trace .t

assert .t & TestEnum.First
assert .t & TestEnum.Second
assert not .t & TestEnum.Third
assert not .t & TestEnum.Fourth


Code: Select all
error: COBRA INTERNAL ERROR / FallThroughException / info=TruthExpr-sh(5840, didBindInh=false, didBindInt=false, didStartBindImp=true, didBindImp=false, token=Token(AMPERSAND, '&', '&', ln 21, col 13, test.cobra), Treatment=AsIs, type=nil, 5840)
Compilation failed - 1 error, 0 warnings

Re: Enum has Flags and bitwise operations

PostPosted: Sun Sep 23, 2012 1:35 pm
by Charles
Certainly it shouldn't give you an internal error. :D

There is a lengthy discussion about this on ticket:265 (http://cobra-language.com/trac/cobra/ticket/265). I'll go through that ticket and your code here, and get this fixed up for 0.9.

Re: Enum has Flags and bitwise operations

PostPosted: Sun Sep 23, 2012 5:06 pm
by Charles
Fixed. Your code should work now except that I think this line should be using | instead of & if you want those assertions to pass:
var t as TestEnum = TestEnum.First & TestEnum.Second
# and the type will be inferred, so that gives us:
var t = TestEnum.First | TestEnum.Second
# you can also use this form, which I prefer:
var t = TestEnum(First, Second)

Re: Enum has Flags and bitwise operations

PostPosted: Sun Sep 23, 2012 5:21 pm
by nerdzero
Oh, shoot yeah. Thanks :)

Re: Enum has Flags and bitwise operations

PostPosted: Wed Sep 26, 2012 1:56 pm
by hopscc
The above is a good example of why the current approach to enums (or more specifically sets of enums) is wrong.
It's tied too closely to the C# implementation (which has issues of its own -Typesafety for one) which uses a thinly covered integer base following on from the C implementation/approach (where ints were all that was available).

Using (the right) bit wise ops for making and testing enum set inclusion is really non obvious to anyone coming to this clean (or not from a C devt background) and even with that it's easy to get wrong.

Cobra cannot (easily) support this same syntax in BE languages that don't implement enums on a integer/numerical (like Java).

The problem comes from both C and C# conflating both enum (a symbolic value) and sets of enums (a set or range of symbolic values) in a single base using a hack on the implementation ( ints and bit wise math) to make it work. It's familiar from c ->c# but it's still wrong.

Cobra would be better off not supporting bit wise ops on enums at all but allowing only assignment and ctor syntax , equality testing and using the 'in' operator for inclusion testing and making the codegen do the right thing- then the question of what (unobvious legacy) syntax to use become moot.
enum AnEnum
a
b
c
d

val = anEnum.a
...
if a == anEnum.b, print 'matches b'
...
s = AnEnum(a,d)
...
If a in s, print 'in set'
# instead of
#s = AnEnum.a | d.AnEnum.d # or using & or whatever
#if a & (AnEnum.a| AnEnum.d)== a, print ...


Raise the abstraction and make it simpler.

Re: Enum has Flags and bitwise operations

PostPosted: Wed Sep 26, 2012 3:43 pm
by Charles
I don't see anything hacky about bits. They really exist and when used this way are often called bitsets. They are not exclusive to C and C#. Python and even Java have bit testing:
http://stackoverflow.com/questions/6067 ... -bits-java

But that same page also references this:
Code: Select all
styles = EnumSet.of(Style.BOLD, Style.ITALIC);

I haven't read far enough to know if EnumSet requires that the enum values are bit-savvy (1, 2, 4, 8, 16, ...) or not, but they indicate that the implementation of EnumSet is.

One thing that bothered me re: our discussion about the related ticket was that if I accepted your proposal that "DayOfWeeks(Saturday, Sunday)" work (where the values are not bit-savvy) then the type would have to be something other than the enum DayOfWeeks. And if it were consistently so, you could not pass it to a .NET library method.

I could see us leaving what we have in place and adding EnumSet or something like it (possibly with some syntactic sugar). I don't think we can get rid of primitive enum bitsets entirely or you won't be able to use libs that require them.

If you want to play with the EnumSet idea and cook up a proposal, feel free. I'm not opposed to revisiting this and making sure that we support both platforms. But my very next priorities are:
-- tag Cobra 0.9 in subversion
-- announce Cobra 0.9 more widely
-- vacation
-- new Snapshot compiler
-- apply your JVM patch
-- another patch of yours (ticket:230)
-- get MonoDevelop and Cobra compiler source playing together
-- ... and more

And of course, things are always in flux.

Re: Enum has Flags and bitwise operations

PostPosted: Wed Sep 26, 2012 9:19 pm
by hopscc
Sorry must have been unclear. I'm not talking about bits and bit sets and bit testing generically. I'm talking about Enums implemented using int values that iIfyou set them the right way can be treated as bit sets and tested using bit operations (this while maybe familiar Is hacky).

Java has EnumSets both for raw bit set usage and for accommodating sets of enums ( re enums they don't have to be done using bitsets but it's fast and convenient to do so). Java enums aren't int related at all so are not required to be Bit savvy (Enums are full blown type-safe classes in their own right). sets of Enums are treated separately as sets... ( the difference are neither here or there it's just different and not directly compatible)

There are two concepts Enums and sets of Enums. They should be presented (cobra wise) separately.
There shouldn't be an issue with mapping into lib code cos the can be merged at code gen time to whatever the BE uses (.net int based contiguous or bit pattern unique values or Enum classes and EnumSets in java, whatever in whatever else).

The high level proposal is to deprecate (or remove) bit twiddling capability in cobra for enums and instead rely on enum ctors and assignment (individual Enum values) and 'val in set' operator (enum sets) for testing value or set inclusion. the BE code generation,rather than translating directly, does an element of mapping to what the BE implementation uses for enums....

this is pretty much what the java BE handlingCodegen does (if I got it close to right)

arrgh - I'll write up something better when I get back - I'm doing this on a iPad and the entry interface is driving me nuts...

Re: Enum has Flags and bitwise operations

PostPosted: Sat Sep 29, 2012 4:57 pm
by kirai84
Still enums of flags would become better without need of writing integer values by hand. It could look like this:
flagenum StateFlags        # "flagenum" keyword instead of "enum".
undefined = 0
whatever
closed
disposed = closed | disposedFlag # Can not be disposed while open.
# Private flags can't be used outside enum declaration.
# They allow to form multiple-bit flags like "disposed" above without typing integer values.
_disposedFlag

turning to this in C#:
Code: Select all
enum StateFlags
{
    Undefined = 0,
    Whatever  = 1,
    Closed    = 2,
    Disposed  = Closed | FlagsEnumExtensions._disposedFlag
}

static class StateFlagsExtensions
{
    internal const StateFlags _disposedFlag = (StateFlags)4;
}


Extensions could also be used to unify .NET enums with Java enums.

Congrats on new release.

Re: Enum has Flags and bitwise operations

PostPosted: Mon Nov 19, 2012 3:57 am
by hopscc
Heres the enum proposal I was getting at for cobra.

This is addressing 2 issues with the current implementation

  • testing Enum set value inclusion (using bit operations) is obscure, error prone,
    non obvious (if not have a good low level coding background) and implementation dependent.

  • Bit operations on Enums on some(one so far) backends are totally unsupportable.

What I would like to do is move the abstraction for these ops up a level to make the above problems disappear
AND make it more obvious what operations you are trying to do.

which is clearer?
if today in weekend, print 'go biking'

if today & weekend == today, print 'take a hike'
# whats the difference if I do this
#if weekend & today, print 'take a hike'
# or this
#if weekend | today, print 'everday take a hike'


So basically the proposal is as follows:

  • Keep the current declaration and initialisation syntax for Enums
    (keep the current setting of Flags Attribute for .Net to indicate use of explicit non colliding bitpattern values)
  • perhaps lose the storageType specification capability - its unsupportable/ignored on java anyway
    Is that used much on .Net?
  • Deprecate/remove the bitwise operations on Enums in favor of only direct comparison (==) and 'in' testing
    (which replaces the bitset twiddling).
    This 'virtualises' the testing operation away from any int based implementation and the need for
    explicit bit twiddling operations but doesnt preclude them being done for supporting a BE implementation (i.e at codegen)


Enum DayOfWeek
Mon, Tues, Wed, Thur, Fri, Sat, Sun
...
today = DayOfWeek.Mon
alsoToday = DayOfWeek(Mon)

assert today == DayOfWeek.Mon
assert alsoToday == today

...
# test explicit value
if today == DayOfWeek.Mon
print 'its Monday'


# groups/sets of enums
weekend = DayOfWeek(Sat, Sun)
workday = DayOfWeek(Mon, Tues, Wed, Thurs, Fri)

#Test inclusion
if today in weekend
print 'go biking'

#if weekend & today == today
# existing syntax test becomes error/unsupported
# transition generate a warning noting the new syntax
# 'Cobra does not use C# syntax for testing enum set inclusion use "today in weekend" instead"

if today in weekday
print 'hi ho hi ho, Its to pay a mortgage I go'

if alsoToday not in DayOfWeek(Mon, Tues, Wed)
print 'nearly the weekend'


At the higher cobra compiler level theres no change apart from losing/deprecating binary Ops on Enums
The only code impact is at codegen (SharpGenerator and JavaGenerator)

.Net conflates Enums and (Bit)sets of Enums into (explicitly set) binary valued Enums.
No change here re representation (still a .Net enum)
just generate the right bit twiddling code for 'enum in Enum(Set)'
(rewrite cobra 'e in E' to C# 'e & E == e' )

Other platforms (that use true symbolic Types for Enums - Java) have to distinguish (at codegen) between uses of
single valued and sets of Enum values and generate the right BE type (done).
The Set inclusion testing operation is done as a mapping to the BE types ( bitset test)

The advantage is that at the cobra level we have a single, clear (always working) high level syntax for enum value
testing that can be easily detected and mapped to the right operation set for the backend in use.

The alternative is to provide/allow a number of testing ops at differing levels of abstraction
(bit twiddling and 'in' and ..)
that different backends support or ignore/errorEmit or try to remap to varying levels of completeness.

Re: Enum has Flags and bitwise operations

PostPosted: Mon Nov 19, 2012 6:27 am
by kobi7
I agree with hopscc (hopscotch?)
plus, a flags enum that is based on integers is limited to 32 if it's uint32, or 64 if it's uint64.
an implementation that uses the Set data-structure avoids this entirely.

of course I don't know many pizza places that have so many flavours ;-)