Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve C99 Compatibility #4

Merged
merged 4 commits into from
Jul 27, 2019
Merged

Improve C99 Compatibility #4

merged 4 commits into from
Jul 27, 2019

Conversation

Gnimuc
Copy link
Member

@Gnimuc Gnimuc commented Jul 22, 2019

This is just a copy of the enum.jl from Julia Base, with minimal tweaks to be in compliance with the C99 standard:

Constraints

2 The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int.

Semantics

3 The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted.109) An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. (The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.) The enumerators of an enumeration are also known as its members.

4 Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined,110) but shall be capable of representing the values of all the members of the enumeration. The enumerated type is incomplete until after the } that terminates the list of enumerator declarations.

Footnotes

  1. Thus, the identifiers of enumeration constants declared in the same scope shall all be distinct from each other and from other identifiers declared in ordinary declarators.

110) An implementation may delay the choice of which integer type until all enumeration constants have been seen.

I don't find anywhere in the standard that specifies the behavior when casting a non-member Integer to Enum, so it is now allowed and the show method will mark it as UnkownMember.

As for those bitwise operators, UInt32 is no longer being treated specially, the return type is promoted. However, it's still an Integer since this is the default behavior of many C/C++ compilers.
One needs to either overload the operator or explicitly cast the return value to the target enum type.

cc @maleadt @SimonDanisch

@codecov-io
Copy link

codecov-io commented Jul 22, 2019

Codecov Report

Merging #4 into master will decrease coverage by 11.35%.
The diff coverage is 56.66%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master       #4       +/-   ##
===========================================
- Coverage   68.49%   57.14%   -11.36%     
===========================================
  Files           1        2        +1     
  Lines          73       91       +18     
===========================================
+ Hits           50       52        +2     
- Misses         23       39       +16
Impacted Files Coverage Δ
src/operators.jl 100% <100%> (ø)
src/CEnum.jl 54.65% <54.11%> (-13.85%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1aa32a3...39e47bd. Read the comment docs.

src/CEnum.jl Outdated Show resolved Hide resolved
@maleadt
Copy link
Member

maleadt commented Jul 23, 2019

Nice! This also makes it possible to use the slightly nicer syntax from Base.@enum:

@cenum Foo::Cint begin
 foo
 bar
end

This looks like a bug though:

julia> @cenum Foo begin
         foo
         bar
       end

julia> typeof(foo)
Cenum Foo:
foo = 0
foo = 0

vs

julia> @enum Foo begin
         foo
         bar
       end

julia> typeof(foo)
Enum Foo:
foo = 0
bar = 1

I don't find anywhere in the standard that specifies the behavior when casting a non-member Integer to Enum, so it is now allowed and the show method will mark it as UnkownMember.

But bitwise operators still just yield the underlying type (#3), I guess that's intended?

@Gnimuc
Copy link
Member Author

Gnimuc commented Jul 24, 2019

But bitwise operators still just yield the underlying type (#3), I guess that's intended?

yes. now this package only defines generic bitwise operators for Cenum-Cenum, Cenum-Integer, and Integer-Cenum inputs. In the example below, it's hard to determine which Cenum type should be chosen as the return type. I think it's ok to just leave this problem to end-users since it's easy to overload these operators and define different promote rules for their own purpose.

julia> using CEnum

julia> @cenum Foo::Cint begin
              foo
              bar
          end

julia> @cenum(Fruit, apple=1, orange=2, kiwi=2)

julia> apple | foo
1

This behavior is the same as the one in C/C++:

C++ > typedef enum {
               xxx,
               yyy,
            } Foo;

C++ > xxx
Cxx.CxxCore.CppEnum{:Foo,UInt32}(0x00000000)

C++ > xxx | yyy
1

@Gnimuc
Copy link
Member Author

Gnimuc commented Jul 24, 2019

This is fixed now:

julia> @cenum(Fruit, apple=1, orange=2, kiwi=2)

julia> typeof(apple)
Cenum Fruit:
apple = 1
orange = 2
kiwi = 2

But as one value could have more than one names in C's enum, it's hard for show method to distinguish those names without using sophisticated data structure like multidict. For simplicity's sake, I think we could treat the following one as a feature, not a bug, since kiwi is indeed orange::Fruit :).

julia> kiwi
orange::Fruit = 2

julia> kiwi === orange
true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants