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

implement flags semantics for enum #2915

Merged
merged 24 commits into from
Jun 19, 2022

Conversation

charles-cooper
Copy link
Member

@charles-cooper charles-cooper commented Jun 16, 2022

What I did

implement operators so that enums can be used like https://docs.python.org/3/library/enum.html#enum.Flag ("Base class for creating enumerated constants that can be combined using the bitwise operations without losing their Flag membership").

This also enables bitwise and/or operators for uint256.

How I did it

Add BITAND, BITOR to the syntax. Implement codegen for &, |. Add clampers for enums - an enum must be in bound for the # of members the enum has (and also nonzero).

How to verify it

see tests, also check compilation of the following test file

# enum.vy
enum Actions:
    BUY
    SELL

@external
def foo(a: Actions) -> bool:
    return a in (Actions.BUY | Actions.SELL)

# note, bitwise ops work on ints now
@external
def bar(x: uint256, y: uint256) -> uint256:
    return x | y & x

Commit message

implement operators so that enums can be used like Python's `enum.Flag`  
("Base class for creating enumerated constants that can be combined 
 using the bitwise operations without losing their Flag membership").
    
this also enables bitwise and/or operators for uint256.             
    
this commit also adds clampers for enums - an enum must be in bound for  
the number of members the enum has (and also, any enum runtime value
must be nonzero).

Description for the changelog

add flags semantics for enums

Cute Animal Picture

image

@codecov-commenter
Copy link

codecov-commenter commented Jun 16, 2022

Codecov Report

Merging #2915 (4efa50a) into master (daeae11) will increase coverage by 0.04%.
The diff coverage is 85.71%.

@@            Coverage Diff             @@
##           master    #2915      +/-   ##
==========================================
+ Coverage   88.30%   88.35%   +0.04%     
==========================================
  Files          96       97       +1     
  Lines       10611    10663      +52     
  Branches     2531     2540       +9     
==========================================
+ Hits         9370     9421      +51     
- Misses        787      791       +4     
+ Partials      454      451       -3     
Impacted Files Coverage Δ
vyper/builtin_functions/functions.py 92.40% <25.00%> (-0.07%) ⬇️
vyper/semantics/types/user/enum.py 80.00% <75.00%> (-0.71%) ⬇️
vyper/ast/nodes.py 93.66% <100.00%> (-0.43%) ⬇️
vyper/codegen/core.py 84.79% <100.00%> (+0.20%) ⬆️
vyper/codegen/expr.py 84.53% <100.00%> (+0.80%) ⬆️
vyper/codegen/types/types.py 88.74% <100.00%> (+0.39%) ⬆️
vyper/semantics/types/user/__init__.py 100.00% <100.00%> (ø)
vyper/semantics/validation/annotation.py 89.67% <100.00%> (+0.17%) ⬆️
vyper/semantics/validation/utils.py 91.48% <100.00%> (+0.18%) ⬆️
... and 6 more

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 daeae11...4efa50a. Read the comment docs.

@charles-cooper charles-cooper marked this pull request as ready for review June 19, 2022 15:15
Copy link
Member

@fubuloubu fubuloubu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would need to see some more tests about storing and manipulating stored values e.g.:

@external
def addMinter(minter: address):
    assert self.roles[msg.sender] in Roles.ADMIN
    self.roles[minter] |= Roles.MINTER

@charles-cooper
Copy link
Member Author

Would need to see some more tests about storing and manipulating stored values e.g.:

@external
def addMinter(minter: address):
    assert self.roles[msg.sender] in Roles.ADMIN
    self.roles[minter] |= Roles.MINTER

nice catch, see 4efa50a

@charles-cooper charles-cooper merged commit 0b20014 into vyperlang:master Jun 19, 2022
@charles-cooper charles-cooper deleted the enum_flags branch June 19, 2022 20:21
@charles-cooper
Copy link
Member Author

oh shoot -- i forgot to tag @tserg in the commit message. he wrote a significant portion of the tests for this PR, wrote the docs, and helped update the grammar for the new ops.

charles-cooper added a commit that referenced this pull request Jun 19, 2022
implement operators so that enums can be used like Python's `enum.Flag`
("Base class for creating enumerated constants that can be combined
using the bitwise operations without losing their Flag membership").

this also enables bitwise and/or operators for uint256, and deprecates
the builtins `bitwise_and` and `bitwise_or`

this commit also adds clampers for enums - an enum must be in bound for
the number of members the enum has (and also, any enum runtime value
must be nonzero).

Co-authored-by: tserg <8017125+tserg@users.noreply.github.com>
@charles-cooper
Copy link
Member Author

fixed the commit message by force pushing from 0b20014 to d675110

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.

None yet

4 participants