Forums

Enum has Flags and bitwise operations

General discussion about Cobra. Releases and general news will also be posted here.
Feel free to ask questions or just say "Hello".

Re: Enum has Flags and bitwise operations

Postby torial » Mon Nov 19, 2012 8:58 am

I like hopscc's proposal as well. Very readable.
torial
 
Posts: 229
Location: IA

Re: Enum has Flags and bitwise operations

Postby Charles » Sat Dec 01, 2012 1:53 pm

Sorry it took me awhile to get back to this thread. Here are my thoughts on hops last post:

Re: "which is clearer" the comparison is a little unfair as your bit test has an extra term in it that is not required. The real comparison is:
if today in weekend, print 'go biking'

if today & weekend, print 'take a hike'


Question: In your proposal, which adds "in" and removes "&" for enums, will it work when checking for multiple values? Like this:
ef = Stuff(E, F) # equiv to Stuff.E | Stuff.F
if ef & stuff, print 'effy'
# will the following work?
ef = Stuff(E, F) # equiv to Stuff.E | Stuff.F
if ef in stuff, print 'effy'


Question: Under your proposal, what are the types of these expressions in the Cobra compiler (before getting to the back-end)? Think of it as what type you could use for a parameter of a method in order that these values could be received?
DayOfWeek.Monday
DayOfWeek(Monday, Tuesday)
Flags(A, B C) # where the enums are valued 1 2 4


Question: Does Java's EnumSet work faster on enums that are "flag-based" (1, 2, 4, 8, 16)? I'm curious.

Comments:

Regarding "perhaps lose the storageType specification capability - its unsupportable/ignored on java", actually it is doable in Java. Consider that in Java, as soon as you want to provide values for your enums (see the "Currency" example on this page), you have to provide a member variable. Which means you can also specify its type. In Cobra:
enum Medium of int64
Air
Land
Water

Converted to Java:
Code: Select all
enum Medium {
   Air(0), Land(1), Water(2)
   private long _value;
   private Medium(long value) {
      this._value = value;
   }
}


One thing I like from Java--and we could do this now--is that when branching/switching on an enum, you can refer to the enum members directly (see switch(day) at http://docs.oracle.com/javase/tutorial/ ... /enum.html). In Cobra, we do this:
branch medium
on Medium.Air, .foo
on Medium.Land, .bar
on Medium.Water, .baz
# but java-style is cleaner:
branch medium
on Air, .foo
on Land, .bar
on Water, .baz
# We cannot allow a "clean gap"!


Anyway, I'm warming up to "a in b" for enums, but I need resolution on above questions, especially types.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Enum has Flags and bitwise operations

Postby hopscc » Wed Dec 05, 2012 5:36 am

a) Leaving off the equality comparison is a bet that you wont ever setup the bit pattern values wrong ( or miss one).
If you do that you will get a non zero result ( evaluates true) that is not the tested value. Its another little gotcha

Q1 Checking for multiple values
The test is reversed
ef = Stuff(E, F) # equiv to Stuff.E | Stuff.F
if ef & stuff, print 'effy'
# This is the equivalent
ef = Stuff(E, F) # equiv to Stuff.E | Stuff.F
if stuff in ef , print 'effy


Just as if you had explicitly defined and setup ef as an explicit bitset and stuff a single bit pattern.


Q2 Types of expressions
They can all unchanged from what they are now (EnumDecl) and
its only at codegen a decision/mapping is made to the correct backend platform type.
( I think it would probably be preferable for clarity if we separated them explicitly in the AST representation and map them individually at code gen but its not necessary to do so - if doing this both would map back to a .Net enum at code gen for .Net - the only difference here is that the multivalue enum would be initialised and flag attribute set by the compiler rather than the programmer doing so explicitly)

The net change is no difference in final representation ( .Net) as currently.
EXCEPT that a cobra programmer is not exposed to the necessity of knowing that multivalues/set inclusion is done explicitly by bit operation tests against explicitly initialised bit/flag patterns and non .Net forms (Java) of enum representations can be (simply though invisibly) supported.


Q3 Enumset faster?
Theres no difference - Javas enums arent 'flag-based' or anything else based - they're symbolic values (static instances of a class) that get mapped to a separate bitset representation for usage for set testing.
Whether the Java Enum classes are extended to support (flag based) values or not is irrelevant to this - the java enums used this way dont need to (in fact cannot) be explicitly set as a particular storage type with particular bit patterns and then explicitly tested using bit ops
.Net/C# here conflates an implementation to a performance hack.

comments comments
Its unsupportable in java not because its not doable (as suggested we can make an implementation that has an embedded type and uses that - I think the current java backend does something like this currently) but because doing so will break against any enums that cobra hasn't created with this implementation i.e any enum used and exposed in a supplied library.
The abstraction immediately leaks for set inclusion testing bit operations on such (non storage type aware and value set) native enums.

Agreed the branch syntax sugar for enum values is a simplification could be done already.
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Enum has Flags and bitwise operations

Postby Charles » Sun Dec 09, 2012 10:57 am

hopscc wrote:a) Leaving off the equality comparison is a bet that you wont ever setup the bit pattern values wrong ( or miss one).
If you do that you will get a non zero result ( evaluates true) that is not the tested value. Its another little gotcha

I don't follow the above reasoning. If you set up the bit pattern wrong, the tests aren't going to work whether you including the extra "== something" or not.

hopscc wrote:Q1 Checking for multiple values
The test is reversed
ef = Stuff(E, F) # equiv to Stuff.E | Stuff.F
if ef & stuff, print 'effy'
# This is the equivalent
ef = Stuff(E, F) # equiv to Stuff.E | Stuff.F
if stuff in ef , print 'effy


Just as if you had explicitly defined and setup ef as an explicit bitset and stuff a single bit pattern.

I was implying that "stuff" itself could have multiple values. Let me try again more explicitly:
a = Stuff(E, F)
b = Stuff(E, G)
if a & b, print 'something'


hopscc wrote:Q2 Types of expressions
They can all unchanged from what they are now (EnumDecl) and
its only at codegen a decision/mapping is made to the correct backend platform type.
( I think it would probably be preferable for clarity if we separated them explicitly in the AST representation and map them individually at code gen but its not necessary to do so - if doing this both would map back to a .Net enum at code gen for .Net - the only difference here is that the multivalue enum would be initialised and flag attribute set by the compiler rather than the programmer doing so explicitly)

I specifically included DayOfWeek because it's not bit-flag based (1, 2, 4, 8, ...) and I recall that you wanted it to work as a set (in the discussion on enums on the ticket). Making the type of "DayOfWeek(Monday, Tuesday)" be a DayOfWeek means the compiler would let you pass it where a DayOfWeek was expected like so:
class A

def foo
days = DayOfWeek(Monday, Tuesday)
.bar(day)

def bar(day as DayOfWeek)
trace day

Do you see the problem there? If not, write the C# for the above.

hopscc wrote:Q3 Enumset faster?
Theres no difference - Javas enums arent 'flag-based' or anything else based - they're symbolic values (static instances of a class) that get mapped to a separate bitset representation for usage for set testing.
Whether the Java Enum classes are extended to support (flag based) values or not is irrelevant to this - the java enums used this way dont need to (in fact cannot) be explicitly set as a particular storage type with particular bit patterns and then explicitly tested using bit ops
.Net/C# here conflates an implementation to a performance hack.


I believe you are correct that the Java enums cannot be bit tested. But you said "cannot... be explicitly set as a particular storage type with particular bit patterns" and that is not true. I even showed example Java code in my post where the initial value and the backing store for the value are provided explicitly.

hopscc wrote:comments comments
Its unsupportable in java not because its not doable (as suggested we can make an implementation that has an embedded type and uses that - I think the current java backend does something like this currently) but because doing so will break against any enums that cobra hasn't created with this implementation i.e any enum used and exposed in a supplied library.
The abstraction immediately leaks for set inclusion testing bit operations on such (non storage type aware and value set) native enums.

But when using library enums, Cobra would just ... use them. It would not generate the declaration for them. The question of supplying the storage type is a question of declaration, not reuse of existing library enums.

hopscc wrote:Agreed the branch syntax sugar for enum values is a simplification could be done already.

Well at least we agree on something. :)
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Enum has Flags and bitwise operations

Postby hopscc » Tue Dec 11, 2012 5:32 am

a) The point is that if you set the bit pattern ( or test ) wrong and dont test the result for equality there are cases (overlapping patterns) where the
expression will appear to work ( evaluate true) when it doesnt match the equality.
In both cases its wrong -if you dont explicitly test, it can 'appear' right

b) alright you want an explicit testing of multival values in both operands:
Lets try and be clear, what are you doing here?
( I had to stare at this to work out what is the intent here)
Its an intersection test - that theres some intersection of the sets of enumvalues between the two operands ( for some indeterminate reason).
Give that, which expresses intent more clearly?
a = Stuff(E,F)
b = Stuff(E,G)
if a & b, print 'something'
# Or
if a.intersection(b).count, print 'something'

( better would be an aliased name/operator .hasCommonality perhaps)
- actually could overload '''in'' to handle this as well - its differentiable on operand types - though the name doesnt intuit as well

a in b, print 'some commonality'

I think for this case (matching against 2 multivalue enums) , anything works better/more clearly than the &/and bit test.

c)To repeat: theres no change - in C#/.Net (coded explicitly) the var and fn call passes an the fncall uses a DayOfWeekEnum.
ditto cobra - In cobra it sets up an EnumDecl for the same thing ( or an MultiValEnumDecl (??) if they get explicitly separated)
c# codegen writes that to a DayOfWeekEnum type for .Net and java codegen writes it as a DayOfWeekEnumBitSet for Java.
Theres no crossover at codegen or at any other time.
(I'm presuming the call to .bar is supposed to be '.bar(days)' not as written)

If theres some other issue that this doesnt address pls tell me explicitly what it is.

d) The problem is not declaration; its the testing or use ( explicitly using bit ops on encoded bit patterns).
Yes we can make a java-for-cobra enum (enum subclass) that implements storage type and values as or not unique bit patterns.
Yes we can then make bit ops on those work in a similar manner to C#/.Net/existing cobra ops.
What we cannot then do (*) is do the same testing/ops using bitops on enums that cobra has not declared (like from system libraries)
because they have a different implementation
( a lesser/simpler impl) - these 'system' enums do not have the storage type/value implementation portions....
so then what?
- just let those tests fail ( malformed code) as the field dereferences fail
- have a different test paradigm for just these enums
- force coders to realise these are different and handle them explicitly and differently

(*) (or at least not without building in some additional internal virtual rewrite of just these system enums )

So back to the original rationale - raise the abstraction, lose the explicit coding implementation detail and make the coding and intent clearer.
better all round

Just out of interest : under what circumstances would being able to specify the enum storage type be an advantage or of use
( and unrelated to max set size or use of bitops for testing set inclusion)?
I'm asking because it seems to me if you lose(hide) the use of bitops for tests you also lose any need to allow specification of storage type ( to fix the max set size).
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Previous

Return to Discussion

Who is online

Users browsing this forum: No registered users and 19 guests

cron